block.c revision 163a4169f98ef0867312fdf70b9389bea7831a8d
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Block driver for media (i.e., flash cards)
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2002 Hewlett-Packard Company
5979ce7208a679b8d012450610d5d5aa75aab3af9Pierre Ossman * Copyright 2005-2008 Pierre Ossman
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use consistent with the GNU GPL is permitted,
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * provided that this copyright notice is
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * preserved in its entirety in all copies and derived works.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FITNESS FOR ANY PARTICULAR PURPOSE.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Many thanks to Alessandro Rubini and Jonathan Corbet!
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author:  Andrew Christian
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *          28 May 2002
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h>
265a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hdreg.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kdev_t.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
31a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven#include <linux/mutex.h>
32ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman#include <linux/scatterlist.h>
33a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman#include <linux/string_helpers.h>
34cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/delay.h>
35cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/capability.h>
36cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/compat.h>
37e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson#include <linux/pm_runtime.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#include <linux/mmc/ioctl.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/card.h>
41385e3227d4d83ab13d7767c4bb3593b0256bf246Pierre Ossman#include <linux/mmc/host.h>
42da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/mmc.h>
43da7fbe58d2d347e95af699ddf04d885be6362bbePierre Ossman#include <linux/mmc/sd.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4798ac2162699f7e9880683cb954891817f20b607cPierre Ossman#include "queue.h"
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
496b0b62853b2553be375033776902640320970846Andy WhitcroftMODULE_ALIAS("mmc:block");
505e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#ifdef MODULE_PARAM_PREFIX
515e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#undef MODULE_PARAM_PREFIX
525e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#endif
535e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson#define MODULE_PARAM_PREFIX "mmcblk."
545e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
556a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_EXT_CSD  113
566a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_ERASE    0x00
576a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_TRIM     0x01
586a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECERASE 0x80
596a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM1 0x81
606a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin#define INAND_CMD38_ARG_SECTRIM2 0x88
618fee476b219d1869762d9ef5c189a0c85e919a4dTrey Ramsay#define MMC_BLK_TIMEOUT_MS  (10 * 60 * 1000)        /* 10 minute timeout */
62775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez#define MMC_SANITIZE_REQ_TIMEOUT 240000
63775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
646a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin
65ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define mmc_req_rel_wr(req)	(((req->cmd_flags & REQ_FUA) || \
66ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				  (req->cmd_flags & REQ_META)) && \
67ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				  (rq_data_dir(req) == WRITE))
68ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define PACKED_CMD_VER	0x01
69ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define PACKED_CMD_WR	0x02
70ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
715e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DEFINE_MUTEX(block_mutex);
726b0b62853b2553be375033776902640320970846Andy Whitcroft
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
745e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * The defaults come from config options but can be overriden by module
755e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * or bootarg options.
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
775e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
781dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse
795e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/*
805e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * We've only got one major, so number of mmcblk devices is
815e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson * limited to 256 / number of minors per device.
825e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson */
835e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic int max_devices;
845e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
855e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson/* 256 minors, so at most 256 separate devices */
865e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonstatic DECLARE_BITMAP(dev_use, 256);
87f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentinstatic DECLARE_BITMAP(name_use, 256);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There is one mmc_blk_data per slot.
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mmc_blk_data {
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t	lock;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct gendisk	*disk;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_queue queue;
96371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct list_head part;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
98d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	unsigned int	flags;
99d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_CMD23	(1 << 0)	/* Can do SET_BLOCK_COUNT for multiblock */
100d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin#define MMC_BLK_REL_WR	(1 << 1)	/* MMC Reliable write support */
101ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon#define MMC_BLK_PACKED_CMD	(1 << 2)	/* MMC packed command support */
102d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int	usage;
104a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	unsigned int	read_only;
105371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned int	part_type;
106f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	unsigned int	name_idx;
10767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	unsigned int	reset_done;
10867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_READ		BIT(0)
10967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_WRITE		BIT(1)
11067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_DISCARD		BIT(2)
11167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter#define MMC_BLK_SECDISCARD	BIT(3)
112371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
113371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	/*
114371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * Only set in main mmc_blk_data associated
115371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * with mmc_card with mmc_set_drvdata, and keeps
116371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 * track of the current selected device partition.
117371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	 */
118371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned int	part_curr;
119371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct device_attribute force_ro;
120add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct device_attribute power_ro_lock;
121add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int	area_type;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
124a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Venstatic DEFINE_MUTEX(open_lock);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
126ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonenum {
127ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	MMC_PACKED_NR_IDX = -1,
128ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	MMC_PACKED_NR_ZERO,
129ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	MMC_PACKED_NR_SINGLE,
130ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon};
131ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1325e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johanssonmodule_param(perdev_minors, int, 0444);
1335e71b7a64cb4c6cff75ca42b535d8227526ec592Olof JohanssonMODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
1345e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
1358d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic inline int mmc_blk_part_switch(struct mmc_card *card,
1368d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy				      struct mmc_blk_data *md);
1378d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic int get_card_status(struct mmc_card *card, u32 *status, int retries);
1388d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
139ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq)
140ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
141ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mqrq->packed;
142ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
143ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
144ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
145ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->cmd_type = MMC_PACKED_NONE;
146ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->nr_entries = MMC_PACKED_NR_ZERO;
147ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->idx_failure = MMC_PACKED_NR_IDX;
148ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->retries = 0;
149ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->blocks = 0;
150ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
151ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md;
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
156a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_lock(&open_lock);
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md = disk->private_data;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md && md->usage == 0)
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md = NULL;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md)
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md->usage++;
162a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_unlock(&open_lock);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return md;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_get_devidx(struct gendisk *disk)
168371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
169163a4169f98ef0867312fdf70b9389bea7831a8dColin Cross	int devidx = disk->first_minor / perdev_minors;
170371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return devidx;
171371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
172371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_put(struct mmc_blk_data *md)
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
175a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_lock(&open_lock);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md->usage--;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md->usage == 0) {
178371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		int devidx = mmc_get_devidx(md->disk);
1795fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter		blk_cleanup_queue(md->queue.queue);
1805fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740Adrian Hunter
1811dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse		__clear_bit(devidx, dev_use);
1821dff314451fa24d6b107aa05393d3169e56a7e0aDavid Woodhouse
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		put_disk(md->disk);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree(md);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
186a621aaed690b9439141c555941b6af53873f6ff1Arjan van de Ven	mutex_unlock(&open_lock);
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
189add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_show(struct device *dev,
190add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		struct device_attribute *attr, char *buf)
191add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{
192add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int ret;
193add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
194add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card = md->queue.card;
195add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int locked = 0;
196add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
197add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
198add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		locked = 2;
199add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
200add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		locked = 1;
201add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
202add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
203add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
204add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return ret;
205add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm}
206add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
207add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmstatic ssize_t power_ro_lock_store(struct device *dev,
208add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		struct device_attribute *attr, const char *buf, size_t count)
209add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm{
210add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	int ret;
211add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_blk_data *md, *part_md;
212add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card;
213add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	unsigned long set;
214add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
215add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (kstrtoul(buf, 0, &set))
216add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		return -EINVAL;
217add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
218add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (set != 1)
219add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		return count;
220add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
221add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md = mmc_blk_get(dev_to_disk(dev));
222add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	card = md->queue.card;
223add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
224e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_get_card(card);
225add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
226add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
227add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->ext_csd.boot_ro_lock |
228add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				EXT_CSD_BOOT_WP_B_PWR_WP_EN,
229add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->ext_csd.part_time);
230add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (ret)
231add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
232add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	else
233add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
234add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
235e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_put_card(card);
236add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
237add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if (!ret) {
238add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		pr_info("%s: Locking boot partition ro until next power on\n",
239add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			md->disk->disk_name);
240add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		set_disk_ro(md->disk, 1);
241add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
242add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		list_for_each_entry(part_md, &md->part, part)
243add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
244add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
245add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				set_disk_ro(part_md->disk, 1);
246add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			}
247add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	}
248add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
249add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	mmc_blk_put(md);
250add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return count;
251add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm}
252add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
253371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
254371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			     char *buf)
255371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
256371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
257371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
258371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
259371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = snprintf(buf, PAGE_SIZE, "%d",
260371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		       get_disk_ro(dev_to_disk(dev)) ^
261371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		       md->read_only);
262371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_put(md);
263371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
264371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
265371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
266371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
267371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      const char *buf, size_t count)
268371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
269371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
270371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	char *end;
271371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
272371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	unsigned long set = simple_strtoul(buf, &end, 0);
273371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (end == buf) {
274371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = -EINVAL;
275371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
276371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
277371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
278371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_disk_ro(dev_to_disk(dev), set || md->read_only);
279371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = count;
280371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout:
281371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_put(md);
282371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
283371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
284371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
285a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Virostatic int mmc_blk_open(struct block_device *bdev, fmode_t mode)
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
287a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = -ENXIO;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2902a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_lock(&block_mutex);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (md->usage == 2)
293a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro			check_disk_change(bdev);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = 0;
295a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman
296a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro		if ((mode & FMODE_WRITE) && md->read_only) {
29770bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton			mmc_blk_put(md);
298a00fc09029f02ca833cf90e5d5625f08c4ac4f51Pierre Ossman			ret = -EROFS;
29970bb08962ea9bd50797ae9f16b2493f5f7c65053Andrew Morton		}
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3012a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_unlock(&block_mutex);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
306db2a144bedd58b3dcf19950c2f476c58c9f39d18Al Virostatic void mmc_blk_release(struct gendisk *disk, fmode_t mode)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
308a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	struct mmc_blk_data *md = disk->private_data;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3102a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_lock(&block_mutex);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_blk_put(md);
3122a48fc0ab24241755dc93bfd4f01d68efab47f5aArnd Bergmann	mutex_unlock(&block_mutex);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
316a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwigmmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
318a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
319a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->heads = 4;
320a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	geo->sectors = 16;
321a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	return 0;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
324cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostruct mmc_blk_ioc_data {
325cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd ic;
326cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned char *buf;
327cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	u64 buf_bytes;
328cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto};
329cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
330cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
331cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd __user *user)
332cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
333cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_ioc_data *idata;
334cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int err;
335cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
336cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata = kzalloc(sizeof(*idata), GFP_KERNEL);
337cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata) {
338cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -ENOMEM;
339aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto out;
340cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
341cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
342cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
343cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
344aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
345cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
346cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
347cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
348cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
349cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EOVERFLOW;
350aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
351cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
352cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
3534d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	if (!idata->buf_bytes)
3544d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		return idata;
3554d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
356cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
357cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata->buf) {
358cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -ENOMEM;
359aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motyka		goto idata_err;
360cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
361cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
362cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_from_user(idata->buf, (void __user *)(unsigned long)
363cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto					idata->ic.data_ptr, idata->buf_bytes)) {
364cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
365cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto copy_err;
366cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
367cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
368cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return idata;
369cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
370cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocopy_err:
371cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata->buf);
372aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaidata_err:
373cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata);
374aea253ecffecd38b5ab97edd73fbe2842a7de371Vladimir Motykaout:
375cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return ERR_PTR(err);
376cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
377cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
3788d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardystatic int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
3798d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy				       u32 retries_max)
3808d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy{
3818d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	int err;
3828d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	u32 retry_count = 0;
3838d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
3848d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (!status || !retries_max)
3858d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		return -EINVAL;
3868d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
3878d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	do {
3888d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = get_card_status(card, status, 5);
3898d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (err)
3908d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			break;
3918d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
3928d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (!R1_STATUS(*status) &&
3938d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy				(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
3948d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			break; /* RPMB programming operation complete */
3958d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
3968d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		/*
3978d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * Rechedule to give the MMC device a chance to continue
3988d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * processing the previous command without being polled too
3998d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * frequently.
4008d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 */
4018d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		usleep_range(1000, 5000);
4028d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	} while (++retry_count < retries_max);
4038d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
4048d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (retry_count == retries_max)
4058d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = -EPERM;
4068d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
4078d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	return err;
4088d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy}
4098d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
410775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erezstatic int ioctl_do_sanitize(struct mmc_card *card)
411775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez{
412775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	int err;
413775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
414a2d1086de6cc3ae2378d9db8b92712911c9e5fefUlf Hansson	if (!mmc_can_sanitize(card)) {
415775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			pr_warn("%s: %s - SANITIZE is not supported\n",
416775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez				mmc_hostname(card->host), __func__);
417775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			err = -EOPNOTSUPP;
418775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			goto out;
419775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	}
420775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
421775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
422775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		mmc_hostname(card->host), __func__);
423775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
424775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
425775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez					EXT_CSD_SANITIZE_START, 1,
426775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez					MMC_SANITIZE_REQ_TIMEOUT);
427775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
428775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	if (err)
429775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
430775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		       mmc_hostname(card->host), __func__, err);
431775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
432775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
433775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez					     __func__);
434775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erezout:
435775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	return err;
436775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez}
437775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
438cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl_cmd(struct block_device *bdev,
439cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_ioc_cmd __user *ic_ptr)
440cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
441cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_ioc_data *idata;
442cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_blk_data *md;
443cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_card *card;
444cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_command cmd = {0};
445cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct mmc_data data = {0};
446ad5fd97288655b5628052c1fa906419417c86100Venkatraman S	struct mmc_request mrq = {NULL};
447cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	struct scatterlist sg;
448cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int err;
4498d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	int is_rpmb = false;
4508d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	u32 status = 0;
451cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
452cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	/*
453cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
454cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * whole block device, not on a partition.  This prevents overspray
455cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * between sibling partitions.
456cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 */
457cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
458cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		return -EPERM;
459cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
460cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
461cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (IS_ERR(idata))
462cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		return PTR_ERR(idata);
463cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
464cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	md = mmc_blk_get(bdev->bd_disk);
465cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!md) {
466cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EINVAL;
4671c02f000e78347aa51822feb189fcb0d90273958Philippe De Swert		goto cmd_err;
468cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
469cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
4708d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
4718d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		is_rpmb = true;
4728d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
473cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	card = md->queue.card;
474cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (IS_ERR(card)) {
475cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = PTR_ERR(card);
476cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_done;
477cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
478cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
4794d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.opcode = idata->ic.opcode;
4804d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.arg = idata->ic.arg;
4814d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	cmd.flags = idata->ic.flags;
4824d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4834d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	if (idata->buf_bytes) {
4844d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.sg = &sg;
4854d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.sg_len = 1;
4864d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.blksz = idata->ic.blksz;
4874d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		data.blocks = idata->ic.blocks;
4884d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4894d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		sg_init_one(data.sg, idata->buf, idata->buf_bytes);
4904d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4914d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if (idata->ic.write_flag)
4924d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.flags = MMC_DATA_WRITE;
4934d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		else
4944d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.flags = MMC_DATA_READ;
4954d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4964d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		/* data.flags must already be set before doing this. */
4974d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		mmc_set_data_timeout(&data, card);
4984d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
4994d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		/* Allow overriding the timeout_ns for empirical tuning. */
5004d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if (idata->ic.data_timeout_ns)
5014d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.timeout_ns = idata->ic.data_timeout_ns;
5024d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5034d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
5044d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			/*
5054d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * Pretend this is a data transfer and rely on the
5064d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * host driver to compute timeout.  When all host
5074d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * drivers support cmd.cmd_timeout for R1B, this
5084d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 * can be changed to:
5094d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *
5104d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *     mrq.data = NULL;
5114d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 *     cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
5124d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			 */
5134d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm			data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
5144d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		}
5154d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5164d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm		mrq.data = &data;
5174d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	}
5184d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
5194d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm	mrq.cmd = &cmd;
5204d6144de8ba263eb3691a737c547e5b2fdc45287Johan Rudholm
521e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_get_card(card);
522cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
5238d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	err = mmc_blk_part_switch(card, md);
5248d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (err)
5258d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		goto cmd_rel_host;
5268d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
527cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->ic.is_acmd) {
528cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = mmc_app_cmd(card->host, card);
529cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		if (err)
530cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			goto cmd_rel_host;
531cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
532cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
5338d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (is_rpmb) {
5348d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = mmc_set_blockcount(card, data.blocks,
5358d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			idata->ic.write_flag & (1 << 31));
5368d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (err)
5378d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			goto cmd_rel_host;
5388d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	}
5398d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
540a82e484e2480583b17be6253b985fa6f582ad20dYaniv Gardi	if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
541a82e484e2480583b17be6253b985fa6f582ad20dYaniv Gardi	    (cmd.opcode == MMC_SWITCH)) {
542775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		err = ioctl_do_sanitize(card);
543775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
544775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		if (err)
545775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			pr_err("%s: ioctl_do_sanitize() failed. err = %d",
546775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez			       __func__, err);
547775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
548775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		goto cmd_rel_host;
549775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	}
550775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez
551cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_wait_for_req(card->host, &mrq);
552cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
553cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (cmd.error) {
554cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
555cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						__func__, cmd.error);
556cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = cmd.error;
557cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
558cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
559cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (data.error) {
560cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		dev_err(mmc_dev(card->host), "%s: data error %d\n",
561cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						__func__, data.error);
562cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = data.error;
563cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
564cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
565cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
566cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	/*
567cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * According to the SD specs, some commands require a delay after
568cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 * issuing the command.
569cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	 */
570cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (idata->ic.postsleep_min_us)
571cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
572cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
573cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (copy_to_user(&(ic_ptr->response), cmd.resp, sizeof(cmd.resp))) {
574cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		err = -EFAULT;
575cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		goto cmd_rel_host;
576cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
577cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
578cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (!idata->ic.write_flag) {
579cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		if (copy_to_user((void __user *)(unsigned long) idata->ic.data_ptr,
580cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto						idata->buf, idata->buf_bytes)) {
581cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			err = -EFAULT;
582cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto			goto cmd_rel_host;
583cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		}
584cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	}
585cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
5868d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	if (is_rpmb) {
5878d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		/*
5888d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * Ensure RPMB command has completed by polling CMD13
5898d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 * "Send Status".
5908d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		 */
5918d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		err = ioctl_rpmb_card_status_poll(card, &status, 5);
5928d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy		if (err)
5938d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy			dev_err(mmc_dev(card->host),
5948d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy					"%s: Card Status=0x%08X, error %d\n",
5958d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy					__func__, status, err);
5968d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy	}
5978d1e977da82ebd1defd44d085edc2c0140aecc2aLoic Pallardy
598cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_rel_host:
599e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	mmc_put_card(card);
600cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
601cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtocmd_done:
602cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	mmc_blk_put(md);
6031c02f000e78347aa51822feb189fcb0d90273958Philippe De Swertcmd_err:
604cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata->buf);
605cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	kfree(idata);
606cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return err;
607cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
608cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
609cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
610cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned int cmd, unsigned long arg)
611cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
612cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	int ret = -EINVAL;
613cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	if (cmd == MMC_IOC_CMD)
614cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto		ret = mmc_blk_ioctl_cmd(bdev, (struct mmc_ioc_cmd __user *)arg);
615cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return ret;
616cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
617cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
618cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT
619cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixtostatic int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
620cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	unsigned int cmd, unsigned long arg)
621cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto{
622cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
623cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto}
624cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif
625cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto
62683d5cde47dedf01b6a4a4331882cbc0a7eea3c2eAlexey Dobriyanstatic const struct block_device_operations mmc_bdops = {
627a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	.open			= mmc_blk_open,
628a5a1561f88fe8bfd7fdceed1d942ad494500b8a9Al Viro	.release		= mmc_blk_release,
629a885c8c4316e1c1d2d2c8755da3f3d14f852528dChristoph Hellwig	.getgeo			= mmc_blk_getgeo,
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
631cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	.ioctl			= mmc_blk_ioctl,
632cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#ifdef CONFIG_COMPAT
633cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto	.compat_ioctl		= mmc_blk_compat_ioctl,
634cb87ea28ed9e75a41eb456bfcb547b4e6f10e750John Calixto#endif
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
637371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic inline int mmc_blk_part_switch(struct mmc_card *card,
638371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				      struct mmc_blk_data *md)
639371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
640371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
641371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *main_md = mmc_get_drvdata(card);
6420d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
643371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (main_md->part_curr == md->part_type)
644371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return 0;
645371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
646371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_card_mmc(card)) {
6470d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		u8 part_config = card->ext_csd.part_config;
6480d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
6490d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
6500d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		part_config |= md->part_type;
651371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
652371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
6530d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter				 EXT_CSD_PART_CONFIG, part_config,
654371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				 card->ext_csd.part_time);
655371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (ret)
656371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			return ret;
6570d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter
6580d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		card->ext_csd.part_config = part_config;
65967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
660371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
661371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	main_md->part_curr = md->part_type;
662371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return 0;
663371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
664371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
665ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossmanstatic u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
666ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman{
667ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	int err;
668051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	u32 result;
669051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	__be32 *blocks;
670ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
671ad5fd97288655b5628052c1fa906419417c86100Venkatraman S	struct mmc_request mrq = {NULL};
6721278dba167f01bb3c6626d16450d31129d041087Chris Ball	struct mmc_command cmd = {0};
673a61ad2b49bfce94dfddce828cd9222e4b9e7825bChris Ball	struct mmc_data data = {0};
674ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
675ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	struct scatterlist sg;
676ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
677ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.opcode = MMC_APP_CMD;
678ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.arg = card->rca << 16;
6797213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
680ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
681ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	err = mmc_wait_for_cmd(card->host, &cmd, 0);
6827213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	if (err)
6837213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell		return (u32)-1;
6847213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
685ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman		return (u32)-1;
686ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
687ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	memset(&cmd, 0, sizeof(struct mmc_command));
688ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
689ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
690ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	cmd.arg = 0;
6917213d175e3b6f6db60f843b72e88857a350e146aDavid Brownell	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
692ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
693ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.blksz = 4;
694ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.blocks = 1;
695ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.flags = MMC_DATA_READ;
696ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.sg = &sg;
697ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	data.sg_len = 1;
698d380443cd0271903bf9516bc04cead81676be034Subhash Jadavani	mmc_set_data_timeout(&data, card);
699ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
700ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mrq.cmd = &cmd;
701ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mrq.data = &data;
702ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
703051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	blocks = kmalloc(4, GFP_KERNEL);
704051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	if (!blocks)
705051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks		return (u32)-1;
706051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks
707051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	sg_init_one(&sg, blocks, 4);
708ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
709ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman	mmc_wait_for_req(card->host, &mrq);
710ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
711051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	result = ntohl(*blocks);
712051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	kfree(blocks);
713051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks
71417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	if (cmd.error || data.error)
715051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks		result = (u32)-1;
716ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
717051913dada046ac948eb6f48c0717fc25de2a917Ben Dooks	return result;
718ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman}
719ec5a19dd935eb3793e1f6ed491e8035b3d7b1df9Pierre Ossman
7200a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linuxstatic int get_card_status(struct mmc_card *card, u32 *status, int retries)
721504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter{
7221278dba167f01bb3c6626d16450d31129d041087Chris Ball	struct mmc_command cmd = {0};
723504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	int err;
724504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter
725504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	cmd.opcode = MMC_SEND_STATUS;
726504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	if (!mmc_host_is_spi(card->host))
727504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter		cmd.arg = card->rca << 16;
728504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter	cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
7290a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	err = mmc_wait_for_cmd(card->host, &cmd, retries);
7300a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	if (err == 0)
7310a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux		*status = cmd.resp[0];
7320a2d4048a22079d7e79d6654bbacbef57bd5728aRussell King - ARM Linux	return err;
733504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter}
734504f191f25b1671802246bac06c9f59f94f0b7deAdrian Hunter
735c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hanssonstatic int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
73695a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson		bool hw_busy_detect, struct request *req, int *gen_err)
737c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson{
738c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
739c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	int err = 0;
740c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	u32 status;
741c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
742c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	do {
743c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		err = get_card_status(card, &status, 5);
744c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (err) {
745c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			pr_err("%s: error %d requesting status\n",
746c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			       req->rq_disk->disk_name, err);
747c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			return err;
748c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		}
749c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
750c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (status & R1_ERROR) {
751c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			pr_err("%s: %s: error sending status cmd, status %#x\n",
752c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson				req->rq_disk->disk_name, __func__, status);
753c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			*gen_err = 1;
754c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		}
755c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
75695a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson		/* We may rely on the host hw to handle busy detection.*/
75795a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson		if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) &&
75895a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson			hw_busy_detect)
75995a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson			break;
76095a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson
761c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		/*
762c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * Timeout if the device never becomes ready for data and never
763c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * leaves the program state.
764c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 */
765c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (time_after(jiffies, timeout)) {
766c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			pr_err("%s: Card stuck in programming state! %s %s\n",
767c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson				mmc_hostname(card->host),
768c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson				req->rq_disk->disk_name, __func__);
769c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			return -ETIMEDOUT;
770c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		}
771c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
772c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		/*
773c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * Some cards mishandle the status bits,
774c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * so make sure to check both the busy
775c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 * indication and the card state.
776c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 */
777c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	} while (!(status & R1_READY_FOR_DATA) ||
778c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
779c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
780c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson	return err;
781c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson}
782c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson
783bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hanssonstatic int send_stop(struct mmc_card *card, unsigned int timeout_ms,
784bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		struct request *req, int *gen_err, u32 *stop_status)
785bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson{
786bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	struct mmc_host *host = card->host;
787bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	struct mmc_command cmd = {0};
788bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	int err;
789bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	bool use_r1b_resp = rq_data_dir(req) == WRITE;
790bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
791bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	/*
792bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	 * Normally we use R1B responses for WRITE, but in cases where the host
793bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	 * has specified a max_busy_timeout we need to validate it. A failure
794bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	 * means we need to prevent the host from doing hw busy detection, which
795bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	 * is done by converting to a R1 response instead.
796bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	 */
797bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
798bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		use_r1b_resp = false;
799bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
800bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	cmd.opcode = MMC_STOP_TRANSMISSION;
801bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	if (use_r1b_resp) {
802bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
803bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		cmd.busy_timeout = timeout_ms;
804bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	} else {
805bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
806bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	}
807bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
808bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	err = mmc_wait_for_cmd(host, &cmd, 5);
809bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	if (err)
810bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		return err;
811bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
812bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	*stop_status = cmd.resp[0];
813bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
814bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	/* No need to check card status in case of READ. */
815bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	if (rq_data_dir(req) == READ)
816bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		return 0;
817bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
818bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	if (!mmc_host_is_spi(host) &&
819bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		(*stop_status & R1_ERROR)) {
820bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		pr_err("%s: %s: general error sending stop command, resp %#x\n",
821bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson			req->rq_disk->disk_name, __func__, *stop_status);
822bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		*gen_err = 1;
823bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	}
824bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
825bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson	return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err);
826bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson}
827bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
828a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma#define ERR_NOMEDIUM	3
829a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_RETRY	2
830a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_ABORT	1
831a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux#define ERR_CONTINUE	0
832a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
833a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_error(struct request *req, const char *name, int error,
834a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	bool status_valid, u32 status)
835a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
836a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	switch (error) {
837a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	case -EILSEQ:
838a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* response crc error, retry the r/w cmd */
839a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: %s sending %s command, card status %#x\n",
840a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			req->rq_disk->disk_name, "response CRC error",
841a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			name, status);
842a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_RETRY;
843a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
844a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	case -ETIMEDOUT:
845a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: %s sending %s command, card status %#x\n",
846a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			req->rq_disk->disk_name, "timed out", name, status);
847a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
848a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* If the status cmd initially failed, retry the r/w cmd */
849a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (!status_valid)
850a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_RETRY;
851a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
852a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/*
853a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * If it was a r/w cmd crc error, or illegal command
854a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * (eg, issued in wrong state) then retry - we should
855a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 * have corrected the state problem above.
856a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		 */
857a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND))
858a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_RETRY;
859a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
860a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* Otherwise abort the command */
861a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
862a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
863a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	default:
864a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		/* We don't understand the error code the driver gave us */
865a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: unknown error %d sending read/write command, card status %#x\n",
866a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		       req->rq_disk->disk_name, error, status);
867a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
868a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
869a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
870a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
871a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux/*
872a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Initial r/w and stop cmd error recovery.
873a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * We don't know whether the card received the r/w cmd or not, so try to
874a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * restore things back to a sane state.  Essentially, we do this as follows:
875a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Obtain card status.  If the first attempt to obtain card status fails,
876a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   the status word will reflect the failed status cmd, not the failed
877a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   r/w cmd.  If we fail to obtain card status, it suggests we can no
878a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   longer communicate with the card.
879a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - Check the card state.  If the card received the cmd but there was a
880a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   transient problem with the response, it might still be in a data transfer
881a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   mode.  Try to send it a stop command.  If this fails, we can't recover.
882a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd failed due to a response CRC error, it was probably
883a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   transient, so retry the cmd.
884a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry.
885a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or
886a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux *   illegal cmd, retry.
887a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux * Otherwise we don't understand what happened, so abort.
888a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux */
889a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linuxstatic int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
890c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
891a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux{
892a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	bool prev_cmd_status_valid = true;
893a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	u32 status, stop_status = 0;
894a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	int err, retry;
895a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
896a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	if (mmc_card_removed(card))
897a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		return ERR_NOMEDIUM;
898a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma
899a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
900a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Try to get card status which indicates both the card state
901a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * and why there was no response.  If the first attempt fails,
902a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * we can't be sure the returned status is for the r/w command.
903a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
904a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	for (retry = 2; retry >= 0; retry--) {
905a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		err = get_card_status(card, &status, 0);
906a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		if (!err)
907a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			break;
908a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
909a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		prev_cmd_status_valid = false;
910a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		pr_err("%s: error %d sending status command, %sing\n",
911a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		       req->rq_disk->disk_name, err, retry ? "retry" : "abort");
912a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
913a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
914a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* We couldn't get a response from the card.  Give up. */
915a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	if (err) {
916a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		/* Check if the card is removed */
917a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		if (mmc_detect_card_removed(card->host))
918a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			return ERR_NOMEDIUM;
919a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return ERR_ABORT;
920a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma	}
921a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
92267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Flag ECC errors */
92367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if ((status & R1_CARD_ECC_FAILED) ||
92467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    (brq->stop.resp[0] & R1_CARD_ECC_FAILED) ||
92567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
92667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		*ecc_err = 1;
92767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
928c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	/* Flag General errors */
929c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
930c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		if ((status & R1_ERROR) ||
931c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			(brq->stop.resp[0] & R1_ERROR)) {
932c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
933c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       req->rq_disk->disk_name, __func__,
934c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       brq->stop.resp[0], status);
935c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			*gen_err = 1;
936c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		}
937c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake
938a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
939a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Check the current card state.  If it is in some data transfer
940a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * mode, tell it to stop (and hopefully transition back to TRAN.)
941a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
942a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
943a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	    R1_CURRENT_STATE(status) == R1_STATE_RCV) {
944bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		err = send_stop(card,
945bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson			DIV_ROUND_UP(brq->data.timeout_ns, 1000000),
946bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson			req, gen_err, &stop_status);
947bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		if (err) {
948a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			pr_err("%s: error %d sending stop command\n",
949a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			       req->rq_disk->disk_name, err);
950bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson			/*
951bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson			 * If the stop cmd also timed out, the card is probably
952bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson			 * not present, so abort. Other errors are bad news too.
953bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson			 */
954a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux			return ERR_ABORT;
955bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson		}
956bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3Ulf Hansson
95767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (stop_status & R1_CARD_ECC_FAILED)
95867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			*ecc_err = 1;
959a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
960a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
961a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Check for set block count errors */
962a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (brq->sbc.error)
963a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error,
964a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				prev_cmd_status_valid, status);
965a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
966a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Check for r/w command errors */
967a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (brq->cmd.error)
968a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		return mmc_blk_cmd_error(req, "r/w cmd", brq->cmd.error,
969a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				prev_cmd_status_valid, status);
970a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
97167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Data errors */
97267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!brq->stop.error)
97367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return ERR_CONTINUE;
97467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
975a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/* Now for stop errors.  These aren't fatal to the transfer. */
9765e1344eb3f4804d2d50195e197fcbcdbd60ad049Johan Rudholm	pr_info("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
977a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	       req->rq_disk->disk_name, brq->stop.error,
978a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	       brq->cmd.resp[0], status);
979a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
980a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	/*
981a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * Subsitute in our own stop status as this will give the error
982a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 * state which happened during the execution of the r/w command.
983a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	 */
984a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	if (stop_status) {
985a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		brq->stop.resp[0] = stop_status;
986a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux		brq->stop.error = 0;
987a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	}
988a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux	return ERR_CONTINUE;
989a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux}
990a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux
99167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
99267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 int type)
99367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
99467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err;
99567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
99667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (md->reset_done & type)
99767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return -EEXIST;
99867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
99967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	md->reset_done |= type;
100067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	err = mmc_hw_reset(host);
100167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/* Ensure we switch back to the correct partition */
100267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (err != -EOPNOTSUPP) {
100367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		struct mmc_blk_data *main_md = mmc_get_drvdata(host->card);
100467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		int part_err;
100567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
100667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		main_md->part_curr = main_md->part_type;
100767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		part_err = mmc_blk_part_switch(host->card, md);
100867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (part_err) {
100967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/*
101067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * We have failed to get back into the correct
101167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * partition, so we need to abort the whole request.
101267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 */
101367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			return -ENODEV;
101467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
101567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
101667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return err;
101767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
101867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
101967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
102067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
102167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	md->reset_done &= ~type;
102267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
102367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
1024bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
1025bd788c9665fb7c543aac21317059375632343337Adrian Hunter{
1026bd788c9665fb7c543aac21317059375632343337Adrian Hunter	struct mmc_blk_data *md = mq->data;
1027bd788c9665fb7c543aac21317059375632343337Adrian Hunter	struct mmc_card *card = md->queue.card;
1028bd788c9665fb7c543aac21317059375632343337Adrian Hunter	unsigned int from, nr, arg;
102967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err = 0, type = MMC_BLK_DISCARD;
1030bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1031bd788c9665fb7c543aac21317059375632343337Adrian Hunter	if (!mmc_can_erase(card)) {
1032bd788c9665fb7c543aac21317059375632343337Adrian Hunter		err = -EOPNOTSUPP;
1033bd788c9665fb7c543aac21317059375632343337Adrian Hunter		goto out;
1034bd788c9665fb7c543aac21317059375632343337Adrian Hunter	}
1035bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1036bd788c9665fb7c543aac21317059375632343337Adrian Hunter	from = blk_rq_pos(req);
1037bd788c9665fb7c543aac21317059375632343337Adrian Hunter	nr = blk_rq_sectors(req);
1038bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1039b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park	if (mmc_can_discard(card))
1040b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park		arg = MMC_DISCARD_ARG;
1041b3bf915308ca2b50f3beec6cc824083870f0f4b5Kyungmin Park	else if (mmc_can_trim(card))
1042bd788c9665fb7c543aac21317059375632343337Adrian Hunter		arg = MMC_TRIM_ARG;
1043bd788c9665fb7c543aac21317059375632343337Adrian Hunter	else
1044bd788c9665fb7c543aac21317059375632343337Adrian Hunter		arg = MMC_ERASE_ARG;
104567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry:
10466a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
10476a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
10486a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_EXT_CSD,
10496a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 arg == MMC_TRIM_ARG ?
10506a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_TRIM :
10516a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_ERASE,
10526a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 0);
10536a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (err)
10546a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			goto out;
10556a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
1056bd788c9665fb7c543aac21317059375632343337Adrian Hunter	err = mmc_erase(card, from, nr, arg);
1057bd788c9665fb7c543aac21317059375632343337Adrian Hunterout:
105867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (err == -EIO && !mmc_blk_reset(md, card->host, type))
105967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		goto retry;
106067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!err)
106167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		mmc_blk_reset_success(md, type);
1062ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani	blk_end_request(req, err, blk_rq_bytes(req));
1063bd788c9665fb7c543aac21317059375632343337Adrian Hunter
1064bd788c9665fb7c543aac21317059375632343337Adrian Hunter	return err ? 0 : 1;
1065bd788c9665fb7c543aac21317059375632343337Adrian Hunter}
1066bd788c9665fb7c543aac21317059375632343337Adrian Hunter
10674980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunterstatic int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
10684980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter				       struct request *req)
10694980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter{
10704980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	struct mmc_blk_data *md = mq->data;
10714980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	struct mmc_card *card = md->queue.card;
1072775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	unsigned int from, nr, arg;
107367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int err = 0, type = MMC_BLK_SECDISCARD;
10744980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
1075775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	if (!(mmc_can_secure_erase_trim(card))) {
10764980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		err = -EOPNOTSUPP;
10774980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		goto out;
10784980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	}
10794980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
1080283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	from = blk_rq_pos(req);
1081283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	nr = blk_rq_sectors(req);
1082283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
1083775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
1084775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		arg = MMC_SECURE_TRIM1_ARG;
1085775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez	else
1086775a9362b5d7e006ff6bbec5cb9c9c9d5a751696Maya Erez		arg = MMC_SECURE_ERASE_ARG;
1087d9ddd62943ee07a75d0428ffcf52f1a747a28c39Kyungmin Park
108867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterretry:
10896a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	if (card->quirks & MMC_QUIRK_INAND_CMD38) {
10906a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
10916a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_EXT_CSD,
10926a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 arg == MMC_SECURE_TRIM1_ARG ?
10936a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_SECTRIM1 :
10946a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 INAND_CMD38_ARG_SECERASE,
10956a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin				 0);
10966a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (err)
1097283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter			goto out_retry;
10986a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
1099283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
11004980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	err = mmc_erase(card, from, nr, arg);
1101283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (err == -EIO)
1102283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		goto out_retry;
1103283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (err)
1104283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		goto out;
1105283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
1106283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (arg == MMC_SECURE_TRIM1_ARG) {
11076a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		if (card->quirks & MMC_QUIRK_INAND_CMD38) {
11086a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
11096a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 INAND_CMD38_ARG_EXT_CSD,
11106a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 INAND_CMD38_ARG_SECTRIM2,
11116a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin					 0);
11126a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin			if (err)
1113283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter				goto out_retry;
11146a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin		}
1115283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
11164980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
1117283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		if (err == -EIO)
1118283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter			goto out_retry;
1119283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter		if (err)
1120283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter			goto out;
11216a7a6b45f454686a1549729bfbae31f0b3b595d6Andrei Warkentin	}
1122283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter
1123283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout_retry:
1124283028122db37621b124f079ca8eae5b64807ad4Adrian Hunter	if (err && !mmc_blk_reset(md, card->host, type))
112567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		goto retry;
112667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!err)
112767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		mmc_blk_reset_success(md, type);
1128283028122db37621b124f079ca8eae5b64807ad4Adrian Hunterout:
1129ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani	blk_end_request(req, err, blk_rq_bytes(req));
11304980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
11314980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	return err ? 0 : 1;
11324980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter}
11334980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter
1134f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentinstatic int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
1135f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{
1136f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	struct mmc_blk_data *md = mq->data;
1137881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	struct mmc_card *card = md->queue.card;
1138881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	int ret = 0;
1139881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon
1140881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	ret = mmc_flush_cache(card);
1141881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	if (ret)
1142881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon		ret = -EIO;
1143f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1144ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani	blk_end_request_all(req, ret);
1145f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1146881d1c25f765938a95def5afe39486ce39f9fc96Seungwon Jeon	return ret ? 0 : 1;
1147f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin}
1148f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1149f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin/*
1150f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * Reformat current write as a reliable write, supporting
1151f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * both legacy and the enhanced reliable write MMC cards.
1152f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * In each transfer we'll handle only as much as a single
1153f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * reliable write can handle, thus finish the request in
1154f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin * partial completions.
1155f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin */
1156d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentinstatic inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
1157d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin				    struct mmc_card *card,
1158d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin				    struct request *req)
1159f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin{
1160f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
1161f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		/* Legacy mode imposes restrictions on transfers. */
1162f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors))
1163f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = 1;
1164f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
1165f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		if (brq->data.blocks > card->ext_csd.rel_sectors)
1166f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = card->ext_csd.rel_sectors;
1167f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		else if (brq->data.blocks < card->ext_csd.rel_sectors)
1168f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			brq->data.blocks = 1;
1169f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	}
1170f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin}
1171f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
11724c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux#define CMD_ERRORS							\
11734c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	(R1_OUT_OF_RANGE |	/* Command argument out of range */	\
11744c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_ADDRESS_ERROR |	/* Misaligned address */		\
11754c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_BLOCK_LEN_ERROR |	/* Transferred block length incorrect */\
11764c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_WP_VIOLATION |	/* Tried to write to protected block */	\
11774c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_CC_ERROR |		/* Card controller error */		\
11784c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux	 R1_ERROR)		/* General/unknown error */
11794c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux
1180ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_err_check(struct mmc_card *card,
1181ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			     struct mmc_async_req *areq)
1182d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin{
1183ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
1184ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin						    mmc_active);
1185ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_blk_request *brq = &mq_mrq->brq;
1186ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct request *req = mq_mrq->req;
1187c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	int ecc_err = 0, gen_err = 0;
1188d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1189d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1190d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * sbc.error indicates a problem with the set block count
1191d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * command.  No data will have been transferred.
1192d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 *
1193d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * cmd.error indicates a problem with the r/w command.  No
1194d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * data will have been transferred.
1195d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 *
1196d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * stop.error indicates a problem with the stop command.  Data
1197d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * may have been transferred, or may still be transferring.
1198d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
119967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
120067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	    brq->data.error) {
1201c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
1202d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_RETRY:
1203d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_RETRY;
1204d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_ABORT:
1205d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_ABORT;
1206a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		case ERR_NOMEDIUM:
1207a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			return MMC_BLK_NOMEDIUM;
1208d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case ERR_CONTINUE:
1209d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1210d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		}
1211d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1212d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1213d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1214d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * Check for errors relating to the execution of the
1215d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * initial command - such as address errors.  No data
1216d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * has been transferred.
1217d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
1218d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (brq->cmd.resp[0] & CMD_ERRORS) {
1219d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		pr_err("%s: r/w command failed, status = %#x\n",
1220d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       req->rq_disk->disk_name, brq->cmd.resp[0]);
1221d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		return MMC_BLK_ABORT;
1222d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1223d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1224d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	/*
1225d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * Everything else is either success, or a data error of some
1226d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * kind.  If it was a write, we may have transitioned to
1227d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 * program mode, which we have to wait for it to complete.
1228d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	 */
1229d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
1230c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		int err;
12318fee476b219d1869762d9ef5c189a0c85e919a4dTrey Ramsay
1232c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		/* Check stop command response */
1233c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		if (brq->stop.resp[0] & R1_ERROR) {
1234c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
1235c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       req->rq_disk->disk_name, __func__,
1236c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			       brq->stop.resp[0]);
1237c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake			gen_err = 1;
1238c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		}
1239c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake
124095a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req,
124195a91298fc09db0c21193ace96d1934598dd92ddUlf Hansson					&gen_err);
1242c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson		if (err)
1243c49433fb66935bd01930e37c7f47d38b6f8135fcUlf Hansson			return MMC_BLK_CMD_ERR;
1244d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1245d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1246c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	/* if general error occurs, retry the write operation. */
1247c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	if (gen_err) {
1248c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		pr_warn("%s: retrying write for general error\n",
1249c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake				req->rq_disk->disk_name);
1250c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake		return MMC_BLK_RETRY;
1251c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake	}
1252c8760069627ad3b0dbbea170f0c4c58b16e18d3dKOBAYASHI Yoshitake
1253d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	if (brq->data.error) {
1254d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
1255d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       req->rq_disk->disk_name, brq->data.error,
1256d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       (unsigned)blk_rq_pos(req),
1257d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       (unsigned)blk_rq_sectors(req),
1258d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		       brq->cmd.resp[0], brq->stop.resp[0]);
1259d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1260d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		if (rq_data_dir(req) == READ) {
126167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (ecc_err)
126267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				return MMC_BLK_ECC_ERR;
1263d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_DATA_ERR;
1264d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		} else {
1265d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			return MMC_BLK_CMD_ERR;
1266d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		}
1267d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	}
1268d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
126967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (!brq->data.bytes_xfered)
127067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return MMC_BLK_RETRY;
1271d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1272ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_packed_cmd(mq_mrq->cmd_type)) {
1273ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (unlikely(brq->data.blocks << 9 != brq->data.bytes_xfered))
1274ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return MMC_BLK_PARTIAL;
1275ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		else
1276ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return MMC_BLK_SUCCESS;
1277ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1278ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
127967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (blk_rq_bytes(req) != brq->data.bytes_xfered)
128067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		return MMC_BLK_PARTIAL;
128167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
128267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return MMC_BLK_SUCCESS;
1283d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin}
1284d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin
1285ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic int mmc_blk_packed_err_check(struct mmc_card *card,
1286ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				    struct mmc_async_req *areq)
1287ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1288ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_queue_req *mq_rq = container_of(areq, struct mmc_queue_req,
1289ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			mmc_active);
1290ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *req = mq_rq->req;
1291ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1292ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	int err, check, status;
1293ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 *ext_csd;
1294ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1295ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1296ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1297ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->retries--;
1298ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	check = mmc_blk_err_check(card, areq);
1299ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	err = get_card_status(card, &status, 0);
1300ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (err) {
1301ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		pr_err("%s: error %d sending status command\n",
1302ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		       req->rq_disk->disk_name, err);
1303ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		return MMC_BLK_ABORT;
1304ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1305ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1306ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (status & R1_EXCEPTION_EVENT) {
1307ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		ext_csd = kzalloc(512, GFP_KERNEL);
1308ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!ext_csd) {
1309ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			pr_err("%s: unable to allocate buffer for ext_csd\n",
1310ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       req->rq_disk->disk_name);
1311ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return -ENOMEM;
1312ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1313ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1314ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		err = mmc_send_ext_csd(card, ext_csd);
1315ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (err) {
1316ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			pr_err("%s: error %d sending ext_csd\n",
1317ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       req->rq_disk->disk_name, err);
1318ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			check = MMC_BLK_ABORT;
1319ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			goto free;
1320ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1321ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1322ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if ((ext_csd[EXT_CSD_EXP_EVENTS_STATUS] &
1323ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		     EXT_CSD_PACKED_FAILURE) &&
1324ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
1325ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		     EXT_CSD_PACKED_GENERIC_ERROR)) {
1326ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
1327ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			    EXT_CSD_PACKED_INDEXED_ERROR) {
1328ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				packed->idx_failure =
1329ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				  ext_csd[EXT_CSD_PACKED_FAILURE_INDEX] - 1;
1330ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				check = MMC_BLK_PARTIAL;
1331ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1332ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			pr_err("%s: packed cmd failed, nr %u, sectors %u, "
1333ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       "failure index: %d\n",
1334ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       req->rq_disk->disk_name, packed->nr_entries,
1335ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			       packed->blocks, packed->idx_failure);
1336ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1337ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonfree:
1338ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		kfree(ext_csd);
1339ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1340ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1341ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return check;
1342ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1343ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
134454d49d77628bed77e5491b8a2a1158a492843a19Per Forlinstatic void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
134554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       struct mmc_card *card,
134654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       int disable_multi,
134754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			       struct mmc_queue *mq)
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
134954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	u32 readcmd, writecmd;
135054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_request *brq = &mqrq->brq;
135154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct request *req = mqrq->req;
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mq->data;
13534265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	bool do_data_tag;
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1355f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	/*
1356f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 * Reliable writes are used to implement Forced Unit Access and
1357f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 * REQ_META accesses, and are supported only on MMCs.
135865299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 *
135965299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 * XXX: this really needs a good explanation of why REQ_META
136065299a3b788bd274bed92f9fa3232082c9f3ea70Christoph Hellwig	 * is treated special.
1361f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	 */
1362f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin	bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
1363f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin			  (req->cmd_flags & REQ_META)) &&
1364f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin		(rq_data_dir(req) == WRITE) &&
1365d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		(md->flags & MMC_BLK_REL_WR);
1366f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
136754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	memset(brq, 0, sizeof(struct mmc_blk_request));
136854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->mrq.cmd = &brq->cmd;
136954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->mrq.data = &brq->data;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
137154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->cmd.arg = blk_rq_pos(req);
137254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (!mmc_card_blockaddr(card))
137354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.arg <<= 9;
137454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
137554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.blksz = 512;
137654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->stop.opcode = MMC_STOP_TRANSMISSION;
137754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->stop.arg = 0;
137854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.blocks = blk_rq_sectors(req);
13796a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter
138054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
138154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * The block layer doesn't support all sector count
138254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * restrictions, so we need to be prepared for too big
138354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * requests.
138454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
138554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks > card->host->max_blk_count)
138654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.blocks = card->host->max_blk_count;
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13882bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley	if (brq->data.blocks > 1) {
13892bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		/*
13902bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * After a read error, we redo the request one sector
13912bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * at a time in order to accurately determine which
13922bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 * sectors can be read successfully.
13932bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		 */
13942bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley		if (disable_multi)
13952bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley			brq->data.blocks = 1;
13962bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley
13972e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto		/*
13982e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto		 * Some controllers have HW issues while operating
13992e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto		 * in multiple I/O mode
14002e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto		 */
14012e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto		if (card->host->ops->multi_io_quirk)
14022e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto			brq->data.blocks = card->host->ops->multi_io_quirk(card,
14032e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto						(rq_data_dir(req) == READ) ?
14042e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto						MMC_DATA_READ : MMC_DATA_WRITE,
14052e47e84245adcb1b3872210678b6146f674fb3ffKuninori Morimoto						brq->data.blocks);
14062bf22b39823c1d173dda31111a4eb2ce36daaf39Paul Walmsley	}
1407d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
140854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks > 1 || do_rel_wr) {
140954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		/* SPI multiblock writes terminate using a special
141054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		 * token, not a STOP_TRANSMISSION request.
1411d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		 */
141254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		if (!mmc_host_is_spi(card->host) ||
141354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		    rq_data_dir(req) == READ)
141454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			brq->mrq.stop = &brq->stop;
141554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		readcmd = MMC_READ_MULTIPLE_BLOCK;
141654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		writecmd = MMC_WRITE_MULTIPLE_BLOCK;
141754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	} else {
141854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->mrq.stop = NULL;
141954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		readcmd = MMC_READ_SINGLE_BLOCK;
142054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		writecmd = MMC_WRITE_BLOCK;
142154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
142254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (rq_data_dir(req) == READ) {
142354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.opcode = readcmd;
142454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.flags |= MMC_DATA_READ;
1425bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson		if (brq->mrq.stop)
1426bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson			brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |
1427bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson					MMC_CMD_AC;
142854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	} else {
142954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->cmd.opcode = writecmd;
143054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.flags |= MMC_DATA_WRITE;
1431bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson		if (brq->mrq.stop)
1432bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson			brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B |
1433bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925Ulf Hansson					MMC_CMD_AC;
143454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
1435d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
143654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (do_rel_wr)
143754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		mmc_apply_rel_rw(brq, card, req);
1438f4c5522b0a8827f39f83f928961d87e081bfe71cAndrei Warkentin
143954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
14404265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	 * Data tag is used only during writing meta data to speed
14414265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	 * up write and any subsequent read of this meta data
14424265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	 */
14434265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	do_data_tag = (card->ext_csd.data_tag_unit_size) &&
14444265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		(req->cmd_flags & REQ_META) &&
14454265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		(rq_data_dir(req) == WRITE) &&
14464265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		((brq->data.blocks * brq->data.blksz) >=
14474265900e0be653f5b78baf2816857ef57cf1332fSaugata Das		 card->ext_csd.data_tag_unit_size);
14484265900e0be653f5b78baf2816857ef57cf1332fSaugata Das
14494265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	/*
145054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * Pre-defined multi-block transfers are preferable to
145154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * open ended-ones (and necessary for reliable writes).
145254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * However, it is not sufficient to just send CMD23,
145354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * and avoid the final CMD12, as on an error condition
145454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * CMD12 (stop) needs to be sent anyway. This, coupled
145554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * with Auto-CMD23 enhancements provided by some
145654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * hosts, means that the complexity of dealing
145754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * with this is best left to the host. If CMD23 is
145854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * supported by card and host, we'll fill sbc in and let
145954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * the host deal with handling it correctly. This means
146054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * that for hosts that don't expose MMC_CAP_CMD23, no
146154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * change of behavior will be observed.
146254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 *
146354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * N.B: Some MMC cards experience perf degradation.
146454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * We'll avoid using CMD23-bounded multiblock writes for
146554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * these, while retaining features like reliable writes.
146654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
14674265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) &&
14684265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) ||
14694265900e0be653f5b78baf2816857ef57cf1332fSaugata Das	     do_data_tag)) {
147054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
147154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.arg = brq->data.blocks |
14724265900e0be653f5b78baf2816857ef57cf1332fSaugata Das			(do_rel_wr ? (1 << 31) : 0) |
14734265900e0be653f5b78baf2816857ef57cf1332fSaugata Das			(do_data_tag ? (1 << 29) : 0);
147454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
147554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->mrq.sbc = &brq->sbc;
147654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
147798ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
147854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	mmc_set_data_timeout(&brq->data, card);
147954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
148054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.sg = mqrq->sg;
148154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
148254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
148354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	/*
148454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * Adjust the sg list so it is the same size as the
148554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 * request.
148654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	 */
148754d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	if (brq->data.blocks != blk_rq_sectors(req)) {
148854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		int i, data_size = brq->data.blocks << 9;
148954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		struct scatterlist *sg;
149054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
149154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
149254d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			data_size -= sg->length;
149354d49d77628bed77e5491b8a2a1158a492843a19Per Forlin			if (data_size <= 0) {
149454d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				sg->length += data_size;
149554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				i++;
149654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin				break;
14976a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter			}
14986a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter		}
149954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin		brq->data.sg_len = i;
150054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	}
150154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin
1502ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	mqrq->mmc_active.mrq = &brq->mrq;
1503ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	mqrq->mmc_active.err_check = mmc_blk_err_check;
1504ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
150554d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	mmc_queue_bounce_pre(mqrq);
150654d49d77628bed77e5491b8a2a1158a492843a19Per Forlin}
15076a79e391df295bd7c2aa1309ea5031f361c197fdAdrian Hunter
1508ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic inline u8 mmc_calc_packed_hdr_segs(struct request_queue *q,
1509ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					  struct mmc_card *card)
1510ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1511ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int hdr_sz = mmc_large_sector(card) ? 4096 : 512;
1512ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int max_seg_sz = queue_max_segment_size(q);
1513ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int len, nr_segs = 0;
1514ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1515ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	do {
1516ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		len = min(hdr_sz, max_seg_sz);
1517ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		hdr_sz -= len;
1518ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		nr_segs++;
1519ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	} while (hdr_sz);
1520ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1521ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return nr_segs;
1522ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1523ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1524ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
1525ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1526ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request_queue *q = mq->queue;
1527ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_card *card = mq->card;
1528ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *cur = req, *next = NULL;
1529ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_blk_data *md = mq->data;
1530ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_queue_req *mqrq = mq->mqrq_cur;
1531ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	bool en_rel_wr = card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN;
1532ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int req_sectors = 0, phys_segments = 0;
1533ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	unsigned int max_blk_count, max_phys_segs;
1534ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	bool put_back = true;
1535ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 max_packed_rw = 0;
1536ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 reqs = 0;
1537ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1538ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (!(md->flags & MMC_BLK_PACKED_CMD))
1539ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1540ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1541ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if ((rq_data_dir(cur) == WRITE) &&
1542ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    mmc_host_packed_wr(card->host))
1543ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		max_packed_rw = card->ext_csd.max_packed_writes;
1544ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1545ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (max_packed_rw == 0)
1546ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1547ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1548ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_req_rel_wr(cur) &&
1549ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
1550ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1551ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1552ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_large_sector(card) &&
1553ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    !IS_ALIGNED(blk_rq_sectors(cur), 8))
1554ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		goto no_packed;
1555ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1556ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mqrq);
1557ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1558ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	max_blk_count = min(card->host->max_blk_count,
1559ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			    card->host->max_req_size >> 9);
1560ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (unlikely(max_blk_count > 0xffff))
1561ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		max_blk_count = 0xffff;
1562ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1563ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	max_phys_segs = queue_max_segments(q);
1564ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	req_sectors += blk_rq_sectors(cur);
1565ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	phys_segments += cur->nr_phys_segments;
1566ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1567ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (rq_data_dir(cur) == WRITE) {
1568ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		req_sectors += mmc_large_sector(card) ? 8 : 1;
1569ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		phys_segments += mmc_calc_packed_hdr_segs(q, card);
1570ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1571ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1572ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	do {
1573ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (reqs >= max_packed_rw - 1) {
1574ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			put_back = false;
1575ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1576ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1577ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1578ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_lock_irq(q->queue_lock);
1579ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		next = blk_fetch_request(q);
1580ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_unlock_irq(q->queue_lock);
1581ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!next) {
1582ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			put_back = false;
1583ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1584ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1585ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1586ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (mmc_large_sector(card) &&
1587ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    !IS_ALIGNED(blk_rq_sectors(next), 8))
1588ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1589ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1590ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (next->cmd_flags & REQ_DISCARD ||
1591ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    next->cmd_flags & REQ_FLUSH)
1592ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1593ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1594ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (rq_data_dir(cur) != rq_data_dir(next))
1595ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1596ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1597ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (mmc_req_rel_wr(next) &&
1598ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		    (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
1599ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1600ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1601ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		req_sectors += blk_rq_sectors(next);
1602ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (req_sectors > max_blk_count)
1603ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1604ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1605ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		phys_segments +=  next->nr_phys_segments;
1606ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (phys_segments > max_phys_segs)
1607ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			break;
1608ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1609ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_add_tail(&next->queuelist, &mqrq->packed->list);
1610ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		cur = next;
1611ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		reqs++;
1612ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	} while (1);
1613ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1614ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (put_back) {
1615ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_lock_irq(q->queue_lock);
1616ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		blk_requeue_request(q, next);
1617ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		spin_unlock_irq(q->queue_lock);
1618ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1619ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1620ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (reqs > 0) {
1621ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_add(&req->queuelist, &mqrq->packed->list);
1622ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		mqrq->packed->nr_entries = ++reqs;
1623ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		mqrq->packed->retries = reqs;
1624ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		return reqs;
1625ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1626ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1627ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonno_packed:
1628ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->cmd_type = MMC_PACKED_NONE;
1629ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return 0;
1630ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1631ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1632ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq,
1633ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					struct mmc_card *card,
1634ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					struct mmc_queue *mq)
1635ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1636ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_blk_request *brq = &mqrq->brq;
1637ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *req = mqrq->req;
1638ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1639ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_blk_data *md = mq->data;
1640ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mqrq->packed;
1641ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	bool do_rel_wr, do_data_tag;
1642ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u32 *packed_cmd_hdr;
1643ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 hdr_blocks;
1644ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 i = 1;
1645ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1646ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1647ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1648ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->cmd_type = MMC_PACKED_WRITE;
1649ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->blocks = 0;
1650ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed->idx_failure = MMC_PACKED_NR_IDX;
1651ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1652ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed_cmd_hdr = packed->cmd_hdr;
1653ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr));
1654ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	packed_cmd_hdr[0] = (packed->nr_entries << 16) |
1655ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		(PACKED_CMD_WR << 8) | PACKED_CMD_VER;
1656ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	hdr_blocks = mmc_large_sector(card) ? 8 : 1;
1657ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1658ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	/*
1659ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	 * Argument for each entry of packed group
1660ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	 */
1661ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	list_for_each_entry(prq, &packed->list, queuelist) {
1662ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		do_rel_wr = mmc_req_rel_wr(prq) && (md->flags & MMC_BLK_REL_WR);
1663ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		do_data_tag = (card->ext_csd.data_tag_unit_size) &&
1664ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(prq->cmd_flags & REQ_META) &&
1665ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(rq_data_dir(prq) == WRITE) &&
1666ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			((brq->data.blocks * brq->data.blksz) >=
1667ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			 card->ext_csd.data_tag_unit_size);
1668ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		/* Argument of CMD23 */
1669ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		packed_cmd_hdr[(i * 2)] =
1670ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) |
1671ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			(do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) |
1672ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			blk_rq_sectors(prq);
1673ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		/* Argument of CMD18 or CMD25 */
1674ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		packed_cmd_hdr[((i * 2)) + 1] =
1675ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			mmc_card_blockaddr(card) ?
1676ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			blk_rq_pos(prq) : blk_rq_pos(prq) << 9;
1677ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		packed->blocks += blk_rq_sectors(prq);
1678ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		i++;
1679ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1680ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1681ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	memset(brq, 0, sizeof(struct mmc_blk_request));
1682ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.cmd = &brq->cmd;
1683ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.data = &brq->data;
1684ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.sbc = &brq->sbc;
1685ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->mrq.stop = &brq->stop;
1686ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1687ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
1688ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->sbc.arg = MMC_CMD23_ARG_PACKED | (packed->blocks + hdr_blocks);
1689ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
1690ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1691ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
1692ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->cmd.arg = blk_rq_pos(req);
1693ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (!mmc_card_blockaddr(card))
1694ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		brq->cmd.arg <<= 9;
1695ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
1696ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1697ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.blksz = 512;
1698ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.blocks = packed->blocks + hdr_blocks;
1699ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.flags |= MMC_DATA_WRITE;
1700ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1701ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->stop.opcode = MMC_STOP_TRANSMISSION;
1702ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->stop.arg = 0;
1703ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
1704ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1705ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_set_data_timeout(&brq->data, card);
1706ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1707ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.sg = mqrq->sg;
1708ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
1709ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1710ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->mmc_active.mrq = &brq->mrq;
1711ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mqrq->mmc_active.err_check = mmc_blk_packed_err_check;
1712ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1713ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_queue_bounce_pre(mqrq);
1714ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1715ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
171667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunterstatic int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
171767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			   struct mmc_blk_request *brq, struct request *req,
171867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			   int ret)
171967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter{
1720ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_queue_req *mq_rq;
1721ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mq_rq = container_of(brq, struct mmc_queue_req, brq);
1722ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
172367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	/*
172467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * If this is an SD card and we're writing, we can first
172567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * mark the known good sectors as ok.
172667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 *
172767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * If the card is not SD, we can still ok written sectors
172867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * as reported by the controller (which might be less than
172967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 * the real number of written sectors, but never more).
173067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	 */
173167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	if (mmc_card_sd(card)) {
173267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		u32 blocks;
173367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
173467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		blocks = mmc_sd_num_wr_blocks(card);
173567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		if (blocks != (u32)-1) {
1736ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani			ret = blk_end_request(req, 0, blocks << 9);
173767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
173867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	} else {
1739ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!mmc_packed_cmd(mq_rq->cmd_type))
1740ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			ret = blk_end_request(req, 0, brq->data.bytes_xfered);
174167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	}
174267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	return ret;
174367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter}
174467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
1745ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq)
1746ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1747ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1748ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1749ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	int idx = packed->idx_failure, i = 0;
1750ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	int ret = 0;
1751ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1752ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1753ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1754ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	while (!list_empty(&packed->list)) {
1755ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		prq = list_entry_rq(packed->list.next);
1756ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (idx == i) {
1757ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			/* retry from error index */
1758ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			packed->nr_entries -= idx;
1759ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			mq_rq->req = prq;
1760ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			ret = 1;
1761ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1762ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (packed->nr_entries == MMC_PACKED_NR_SINGLE) {
1763ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				list_del_init(&prq->queuelist);
1764ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_clear_packed(mq_rq);
1765ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1766ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			return ret;
1767ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1768ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_del_init(&prq->queuelist);
1769ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		blk_end_request(prq, 0, blk_rq_bytes(prq));
1770ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		i++;
1771ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1772ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1773ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mq_rq);
1774ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	return ret;
1775ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1776ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1777ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq)
1778ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1779ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1780ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1781ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1782ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1783ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1784ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	while (!list_empty(&packed->list)) {
1785ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		prq = list_entry_rq(packed->list.next);
1786ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		list_del_init(&prq->queuelist);
1787ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		blk_end_request(prq, -EIO, blk_rq_bytes(prq));
1788ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1789ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1790ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mq_rq);
1791ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1792ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1793ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeonstatic void mmc_blk_revert_packed_req(struct mmc_queue *mq,
1794ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				      struct mmc_queue_req *mq_rq)
1795ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon{
1796ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request *prq;
1797ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct request_queue *q = mq->queue;
1798ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	struct mmc_packed *packed = mq_rq->packed;
1799ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1800ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	BUG_ON(!packed);
1801ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1802ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	while (!list_empty(&packed->list)) {
1803ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		prq = list_entry_rq(packed->list.prev);
1804ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (prq->queuelist.prev != &packed->list) {
1805ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			list_del_init(&prq->queuelist);
1806ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			spin_lock_irq(q->queue_lock);
1807ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			blk_requeue_request(mq->queue, prq);
1808ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			spin_unlock_irq(q->queue_lock);
1809ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		} else {
1810ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			list_del_init(&prq->queuelist);
1811ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		}
1812ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
1813ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1814ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	mmc_blk_clear_packed(mq_rq);
1815ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon}
1816ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1817ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlinstatic int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
181854d49d77628bed77e5491b8a2a1158a492843a19Per Forlin{
181954d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_data *md = mq->data;
182054d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_card *card = md->queue.card;
182154d49d77628bed77e5491b8a2a1158a492843a19Per Forlin	struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
182267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter	int ret = 1, disable_multi = 0, retry = 0, type;
1823d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin	enum mmc_blk_status status;
1824ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_queue_req *mq_rq;
1825a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das	struct request *req = rqc;
1826ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	struct mmc_async_req *areq;
1827ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	const u8 packed_nr = 2;
1828ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	u8 reqs = 0;
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1830ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (!rqc && !mq->mqrq_prev->req)
1831ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		return 0;
183298ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
1833ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (rqc)
1834ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		reqs = mmc_blk_prep_packed_list(mq, rqc);
1835ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1836ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	do {
1837ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (rqc) {
1838a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			/*
1839a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			 * When 4KB native sector is enabled, only 8 blocks
1840a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			 * multiple read or write is allowed
1841a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			 */
1842a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			if ((brq->data.blocks & 0x07) &&
1843a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			    (card->ext_csd.data_sector_size == 4096)) {
1844a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das				pr_err("%s: Transfer size is not 4KB sector size aligned\n",
1845a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das					req->rq_disk->disk_name);
1846ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mq_rq = mq->mqrq_cur;
1847a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das				goto cmd_abort;
1848a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das			}
1849ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1850ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (reqs >= packed_nr)
1851ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur,
1852ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon							    card, mq);
1853ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			else
1854ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
1855ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			areq = &mq->mqrq_cur->mmc_active;
1856ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		} else
1857ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			areq = NULL;
1858ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		areq = mmc_start_req(card->host, areq, (int *) &status);
18592220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		if (!areq) {
18602220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			if (status == MMC_BLK_NEW_REQUEST)
18612220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman				mq->flags |= MMC_QUEUE_NEW_REQUEST;
1862ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			return 0;
18632220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		}
1864ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
1865ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
1866ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		brq = &mq_rq->brq;
1867ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		req = mq_rq->req;
186867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
1869ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		mmc_queue_bounce_post(mq_rq);
187098ccf14909ba02a41c5925b0b2c92aeeef23d3b9Pierre Ossman
1871d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		switch (status) {
1872d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_SUCCESS:
1873d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_PARTIAL:
1874d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			/*
1875d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * A block was successfully transferred.
1876d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 */
187767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			mmc_blk_reset_success(md, type);
1878ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1879ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (mmc_packed_cmd(mq_rq->cmd_type)) {
1880ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				ret = mmc_blk_end_packed_req(mq_rq);
1881ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				break;
1882ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			} else {
1883ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				ret = blk_end_request(req, 0,
1884d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin						brq->data.bytes_xfered);
1885ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1886ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
188767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/*
188867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * If the blk_end_request function returns non-zero even
188967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * though all data has been transferred and no errors
189067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 * were returned by the host controller, it's a bug.
189167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			 */
1892ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			if (status == MMC_BLK_SUCCESS && ret) {
1893a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S				pr_err("%s BUG rq_tot %d d_xfer %d\n",
1894ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				       __func__, blk_rq_bytes(req),
1895ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				       brq->data.bytes_xfered);
1896ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				rqc = NULL;
1897ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				goto cmd_abort;
1898ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			}
1899d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1900d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_CMD_ERR:
190167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			ret = mmc_blk_cmd_err(md, card, brq, req, ret);
190267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!mmc_blk_reset(md, card->host, type))
190367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
190467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			goto cmd_abort;
1905d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_RETRY:
1906d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			if (retry++ < 5)
1907a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux				break;
190867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/* Fall through */
1909d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin		case MMC_BLK_ABORT:
191067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!mmc_blk_reset(md, card->host, type))
191167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
19124c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux			goto cmd_abort;
191367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		case MMC_BLK_DATA_ERR: {
191467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			int err;
191567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter
191667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			err = mmc_blk_reset(md, card->host, type);
191767716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (!err)
191867716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
1919ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (err == -ENODEV ||
1920ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_packed_cmd(mq_rq->cmd_type))
192167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				goto cmd_abort;
192267716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			/* Fall through */
192367716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		}
192467716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter		case MMC_BLK_ECC_ERR:
192567716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			if (brq->data.blocks > 1) {
192667716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				/* Redo read one sector at a time */
19276606110d89aefcb21b9e70adfe064987cbd8393aJoe Perches				pr_warn("%s: retrying using single block read\n",
19286606110d89aefcb21b9e70adfe064987cbd8393aJoe Perches					req->rq_disk->disk_name);
192967716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				disable_multi = 1;
193067716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter				break;
193167716327eec7e9d573e7cb2d806545d6f7c1a38dAdrian Hunter			}
1932d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			/*
1933d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * After an error, we redo I/O one sector at a
1934d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * time, so we only reach here after trying to
1935d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 * read a single sector.
1936d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			 */
1937ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani			ret = blk_end_request(req, -EIO,
1938d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin						brq->data.blksz);
1939ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			if (!ret)
1940ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin				goto start_new_req;
1941d78d4a8ad53f345dd3c0bb5f8d377baa523739f7Per Forlin			break;
1942a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma		case MMC_BLK_NOMEDIUM:
1943a8ad82cc1b22d04916d9cdb1dc75052e80ac803cSujit Reddy Thumma			goto cmd_abort;
19442220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		default:
19452220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			pr_err("%s: Unhandled return value (%d)",
19462220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman					req->rq_disk->disk_name, status);
19472220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			goto cmd_abort;
19484c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux		}
19494c2b8f26eb8b54203e0e7834e0f7a11a7ae15ef1Russell King - ARM Linux
1950ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (ret) {
1951ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (mmc_packed_cmd(mq_rq->cmd_type)) {
1952ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				if (!mq_rq->packed->retries)
1953ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					goto cmd_abort;
1954ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq);
1955ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_start_req(card->host,
1956ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					      &mq_rq->mmc_active, NULL);
1957ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			} else {
1958ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
1959ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				/*
1960ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				 * In case of a incomplete request
1961ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				 * prepare it again and resend.
1962ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				 */
1963ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_rw_rq_prep(mq_rq, card,
1964ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon						disable_multi, mq);
1965ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_start_req(card->host,
1966ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon						&mq_rq->mmc_active, NULL);
1967ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			}
1968ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		}
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (ret);
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1973a01f3ccf845067de32189f8a8e85d22c381f93b9Russell King - ARM Linux cmd_abort:
1974ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_packed_cmd(mq_rq->cmd_type)) {
1975ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		mmc_blk_abort_packed_req(mq_rq);
1976ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	} else {
1977ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (mmc_card_removed(card))
1978ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			req->cmd_flags |= REQ_QUIET;
1979ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		while (ret)
1980ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			ret = blk_end_request(req, -EIO,
1981ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon					blk_rq_cur_bytes(req));
1982ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1984ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin start_new_req:
1985ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (rqc) {
19867a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon		if (mmc_card_removed(card)) {
19877a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			rqc->cmd_flags |= REQ_QUIET;
19887a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			blk_end_request_all(rqc, -EIO);
19897a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon		} else {
1990ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			/*
1991ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			 * If current request is packed, it needs to put back.
1992ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			 */
1993ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			if (mmc_packed_cmd(mq->mqrq_cur->cmd_type))
1994ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon				mmc_blk_revert_packed_req(mq, mq->mqrq_cur);
1995ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
19967a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
19977a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon			mmc_start_req(card->host,
19987a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon				      &mq->mqrq_cur->mmc_active, NULL);
19997a81902fa52f2b6f5037e167f74ebb5a41cfc7d1Seungwon Jeon		}
2000ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	}
2001ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2005bd788c9665fb7c543aac21317059375632343337Adrian Hunterstatic int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
2006bd788c9665fb7c543aac21317059375632343337Adrian Hunter{
20071a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	int ret;
20081a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	struct mmc_blk_data *md = mq->data;
20091a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	struct mmc_card *card = md->queue.card;
20102220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman	struct mmc_host *host = card->host;
20112220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman	unsigned long flags;
2012f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	unsigned int cmd_flags = req ? req->cmd_flags : 0;
20131a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
2014ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin	if (req && !mq->mqrq_prev->req)
2015ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		/* claim host only for the first request */
2016e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		mmc_get_card(card);
2017ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin
2018371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = mmc_blk_part_switch(card, md);
2019371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (ret) {
20200d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		if (req) {
2021ecf8b5d0a378a0f922ffca27bd0a9101f246fa11Subhash Jadavani			blk_end_request_all(req, -EIO);
20220d7d85ca6e5dc7bd426d1d5989a44e93e8c7a0d3Adrian Hunter		}
2023371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		ret = 0;
2024371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
2025371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
20261a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
20272220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman	mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
2028f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	if (cmd_flags & REQ_DISCARD) {
2029ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		/* complete ongoing async transfer before issuing discard */
2030ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin		if (card->host->areq)
2031ee8a43a51c7681f19fe23b6b936e1d8094a8b7d1Per Forlin			mmc_blk_issue_rw_rq(mq, NULL);
20325204d00f06ac9af4ef9c469cce7f9bbe179739b1Lukas Czerner		if (req->cmd_flags & REQ_SECURE)
20331a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin			ret = mmc_blk_issue_secdiscard_rq(mq, req);
20344980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter		else
20351a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin			ret = mmc_blk_issue_discard_rq(mq, req);
2036f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	} else if (cmd_flags & REQ_FLUSH) {
2037393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung		/* complete ongoing async transfer before issuing flush */
2038393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung		if (card->host->areq)
2039393f9a08e2ee72e42379489a5781feaf9c406d5fJaehoon Chung			mmc_blk_issue_rw_rq(mq, NULL);
20401a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin		ret = mmc_blk_issue_flush(mq, req);
20414980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	} else {
20422220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		if (!req && host->areq) {
20432220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			spin_lock_irqsave(&host->context_info.lock, flags);
20442220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			host->context_info.is_waiting_last_req = true;
20452220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman			spin_unlock_irqrestore(&host->context_info.lock, flags);
20462220eedfd7aea69008173a224975e10284fbe854Konstantin Dorfman		}
20471a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin		ret = mmc_blk_issue_rw_rq(mq, req);
20484980454868af4b2f84f1f15f4b76512eecb37e1dAdrian Hunter	}
20491a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin
2050371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinout:
2051ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon	if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
2052f662ae48ae67dfd42739e65750274fe8de46240aRay Jui	     (cmd_flags & MMC_REQ_SPECIAL_MASK))
2053ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		/*
2054ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * Release host when there are no more requests
2055ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * and after special request(discard, flush) is done.
2056ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * In case sepecial request, there is no reentry to
2057ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
2058ef3a69c7a40d5350adeaed7f0f4b4dcf6362dbbdSeungwon Jeon		 */
2059e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		mmc_put_card(card);
20601a258db6f396e26c2c00b19c0107a891895d4584Andrei Warkentin	return ret;
2061bd788c9665fb7c543aac21317059375632343337Adrian Hunter}
20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2063a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell Kingstatic inline int mmc_blk_readonly(struct mmc_card *card)
2064a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King{
2065a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	return mmc_card_readonly(card) ||
2066a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	       !(card->csd.cmdclass & CCC_BLOCK_WRITE);
2067a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King}
2068a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2069371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
2070371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      struct device *parent,
2071371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      sector_t size,
2072371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin					      bool default_ro,
2073add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					      const char *subname,
2074add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					      int area_type)
20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md;
20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int devidx, ret;
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20795e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	devidx = find_first_zero_bit(dev_use, max_devices);
20805e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	if (devidx >= max_devices)
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENOSPC);
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__set_bit(devidx, dev_use);
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2084dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau	md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
2085a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (!md) {
2086a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		ret = -ENOMEM;
2087a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto out;
2088a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	}
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2090a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	/*
2091f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * !subname implies we are creating main mmc_blk_data that will be
2092f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * associated with mmc_card with mmc_set_drvdata. Due to device
2093f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * partitions, devidx will not coincide with a per-physical card
2094f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 * index anymore so we keep track of a name index.
2095f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	 */
2096f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	if (!subname) {
2097f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		md->name_idx = find_first_zero_bit(name_use, max_devices);
2098f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		__set_bit(md->name_idx, name_use);
2099add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	} else
2100f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		md->name_idx = ((struct mmc_blk_data *)
2101f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin				dev_to_disk(parent)->private_data)->name_idx;
2102f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin
2103add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md->area_type = area_type;
2104add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2105f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	/*
2106a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * Set the read-only status based on the supported commands
2107a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * and the write protect switch.
2108a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 */
2109a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->read_only = mmc_blk_readonly(card);
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21115e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	md->disk = alloc_disk(perdev_minors);
2112a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (md->disk == NULL) {
2113a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		ret = -ENOMEM;
2114a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto err_kfree;
2115a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	}
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2117a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	spin_lock_init(&md->lock);
2118371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	INIT_LIST_HEAD(&md->part);
2119a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->usage = 1;
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121d09408ade08a08a710a247fb52aa50101e73ebf7Adrian Hunter	ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
2122a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	if (ret)
2123a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King		goto err_putdisk;
21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2125a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->queue.issue_fn = mmc_blk_issue_rq;
2126a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->queue.data = md;
2127d2b18394259ef621fd2a6322aa9934198fd87a6aRussell King
2128fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	md->disk->major	= MMC_BLOCK_MAJOR;
21295e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	md->disk->first_minor = devidx * perdev_minors;
2130a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->fops = &mmc_bdops;
2131a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->private_data = md;
2132a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	md->disk->queue = md->queue.queue;
2133371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->disk->driverfs_dev = parent;
2134371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_disk_ro(md->disk, md->read_only || default_ro);
2135163a4169f98ef0867312fdf70b9389bea7831a8dColin Cross	md->disk->flags = GENHD_FL_EXT_DEVT;
2136f5b4d71f72c5f08c2e1d0af68ef881f85537e7a1Ulf Hansson	if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT))
213753d8f97462b0bbb51150f4d6bc2fd45336a008b9Loic Pallardy		md->disk->flags |= GENHD_FL_NO_PART_SCAN;
2138a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2139a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	/*
2140a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
2141a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 *
2142a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * - be set for removable media with permanent block devices
2143a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * - be unset for removable block devices with permanent media
2144a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 *
2145a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * Since MMC block devices clearly fall under the second
2146a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * case, we do not set GENHD_FL_REMOVABLE.  Userspace
2147a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * should use the block device creation/destruction hotplug
2148a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 * messages to tell when the card is present.
2149a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King	 */
2150a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2151f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
2152f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin		 "mmcblk%d%s", md->name_idx, subname ? subname : "");
2153a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2154a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das	if (mmc_card_mmc(card))
2155a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das		blk_queue_logical_block_size(md->queue.queue,
2156a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das					     card->ext_csd.data_sector_size);
2157a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das	else
2158a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das		blk_queue_logical_block_size(md->queue.queue, 512);
2159a5075eb94837edde6833fd5e0277fc2370cf8b39Saugata Das
2160371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	set_capacity(md->disk, size);
2161d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2162f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin	if (mmc_host_cmd23(card->host)) {
2163f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		if (mmc_card_mmc(card) ||
2164f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		    (mmc_card_sd(card) &&
2165f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin		     card->scr.cmds & SD_SCR_CMD23_SUPPORT))
2166f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin			md->flags |= MMC_BLK_CMD23;
2167f0d89972b01798cf9d245dfa1cacfa0ee78a3593Andrei Warkentin	}
2168d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2169d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	if (mmc_card_mmc(card) &&
2170d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	    md->flags & MMC_BLK_CMD23 &&
2171d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	    ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
2172d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	     card->ext_csd.rel_sectors)) {
2173d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		md->flags |= MMC_BLK_REL_WR;
2174d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA);
2175d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	}
2176d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2177ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	if (mmc_card_mmc(card) &&
2178ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    (area_type == MMC_BLK_DATA_AREA_MAIN) &&
2179ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    (md->flags & MMC_BLK_CMD23) &&
2180ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	    card->ext_csd.packed_event_en) {
2181ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon		if (!mmc_packed_init(&md->queue, card))
2182ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon			md->flags |= MMC_BLK_PACKED_CMD;
2183ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon	}
2184ce39f9d17c14e56ea6772aa84393e6e0cc8499c4Seungwon Jeon
2185371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return md;
2186371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2187371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_putdisk:
2188371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	put_disk(md->disk);
2189371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin err_kfree:
2190371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	kfree(md);
2191371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin out:
2192371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ERR_PTR(ret);
2193371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2194371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2195371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
2196371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2197371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	sector_t size;
2198371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md;
2199a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
220085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
220185a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		/*
220285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * The EXT_CSD sector count is in number or 512 byte
220385a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * sectors.
220485a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 */
2205371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		size = card->ext_csd.sectors;
220685a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	} else {
220785a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		/*
220885a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * The CSD capacity field is in units of read_blkbits.
220985a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 * set_capacity takes units of 512 bytes.
221085a18ad93ec66888d85758630019b10a84257f3cPierre Ossman		 */
2211371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		size = card->csd.capacity << (card->csd.read_blkbits - 9);
221285a18ad93ec66888d85758630019b10a84257f3cPierre Ossman	}
2213371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2214add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	md = mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
2215add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					MMC_BLK_DATA_AREA_MAIN);
22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return md;
2217371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2218a6f6c96b65d7f65a7a7bf5cbe874eda182a6b2ccRussell King
2219371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_part(struct mmc_card *card,
2220371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      struct mmc_blk_data *md,
2221371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      unsigned int part_type,
2222371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      sector_t size,
2223371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			      bool default_ro,
2224add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			      const char *subname,
2225add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			      int area_type)
2226371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2227371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	char cap_str[10];
2228371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
2229371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2230371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
2231add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				    subname, area_type);
2232371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (IS_ERR(part_md))
2233371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return PTR_ERR(part_md);
2234371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	part_md->part_type = part_type;
2235371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_add(&part_md->part, &md->part);
2236371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2237371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2,
2238371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			cap_str, sizeof(cap_str));
2239a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S	pr_info("%s: %s %s partition %u %s\n",
2240371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	       part_md->disk->disk_name, mmc_card_id(card),
2241371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	       mmc_card_name(card), part_md->part_type, cap_str);
2242371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return 0;
2243371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2244371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2245e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon/* MMC Physical partitions consist of two boot partitions and
2246e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * up to four general purpose partitions.
2247e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * For each partition enabled in EXT_CSD a block device will be allocatedi
2248e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon * to provide access to the partition.
2249e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon */
2250e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon
2251371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
2252371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2253e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon	int idx, ret = 0;
2254371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2255371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (!mmc_card_mmc(card))
2256371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		return 0;
2257371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2258e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon	for (idx = 0; idx < card->nr_parts; idx++) {
2259e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon		if (card->part[idx].size) {
2260e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon			ret = mmc_blk_alloc_part(card, md,
2261e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].part_cfg,
2262e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].size >> 9,
2263e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				card->part[idx].force_ro,
2264add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->part[idx].name,
2265add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				card->part[idx].area_type);
2266e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon			if (ret)
2267e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon				return ret;
2268e0c368d571d946ff40f068344b5c2df90c93dd2eNamjae Jeon		}
2269371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2270371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2271371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
22721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2274371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_req(struct mmc_blk_data *md)
2275371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2276add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card;
2277add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2278371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (md) {
2279fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		/*
2280fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 * Flush remaining requests and free queues. It
2281fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 * is freeing the queue that stops new requests
2282fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 * from being accepted.
2283fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		 */
22848efb83a2f8518a6ffcc074177f8d659c5165ef37Franck Jullien		card = md->queue.card;
2285fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		mmc_cleanup_queue(&md->queue);
2286fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom		if (md->flags & MMC_BLK_PACKED_CMD)
2287fdfa20c1631210d0ca218689204682ea80e170e3Paul Taysom			mmc_packed_clean(&md->queue);
2288371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (md->disk->flags & GENHD_FL_UP) {
2289371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			device_remove_file(disk_to_dev(md->disk), &md->force_ro);
2290add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
2291add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					card->ext_csd.boot_ro_lockable)
2292add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				device_remove_file(disk_to_dev(md->disk),
2293add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					&md->power_ro_lock);
2294371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2295371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			del_gendisk(md->disk);
2296371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
2297371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		mmc_blk_put(md);
2298371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2299371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2300371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2301371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic void mmc_blk_remove_parts(struct mmc_card *card,
2302371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin				 struct mmc_blk_data *md)
2303371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2304371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct list_head *pos, *q;
2305371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
2306371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2307f06c9153f5ecd47dfed23f87b9d08e42ff0e4170Andrei Warkentin	__clear_bit(md->name_idx, name_use);
2308371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_for_each_safe(pos, q, &md->part) {
2309371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		part_md = list_entry(pos, struct mmc_blk_data, part);
2310371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_del(pos);
2311371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		mmc_blk_remove_req(part_md);
2312371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2313371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2314371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2315371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentinstatic int mmc_add_disk(struct mmc_blk_data *md)
2316371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin{
2317371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	int ret;
2318add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	struct mmc_card *card = md->queue.card;
2319371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2320371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	add_disk(md->disk);
2321371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.show = force_ro_show;
2322371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.store = force_ro_store;
2323641c3187b9d53cfd4c23b0ce2ab18a13d5e775e5Rabin Vincent	sysfs_attr_init(&md->force_ro.attr);
2324371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.attr.name = "force_ro";
2325371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
2326371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
2327371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (ret)
2328add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		goto force_ro_fail;
2329add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2330add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
2331add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	     card->ext_csd.boot_ro_lockable) {
233288187398cc5fa6650f38b9dcd5464667f468888fAl Viro		umode_t mode;
2333add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2334add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
2335add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			mode = S_IRUGO;
2336add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		else
2337add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			mode = S_IRUGO | S_IWUSR;
2338add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2339add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.show = power_ro_lock_show;
2340add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.store = power_ro_lock_store;
234100d9ac08757049f334803b3d4dd202a6b1687dabRabin Vincent		sysfs_attr_init(&md->power_ro_lock.attr);
2342add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.attr.mode = mode;
2343add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		md->power_ro_lock.attr.name =
2344add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm					"ro_lock_until_next_power_on";
2345add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		ret = device_create_file(disk_to_dev(md->disk),
2346add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm				&md->power_ro_lock);
2347add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm		if (ret)
2348add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm			goto power_ro_lock_fail;
2349add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	}
2350add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	return ret;
2351add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm
2352add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmpower_ro_lock_fail:
2353add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	device_remove_file(disk_to_dev(md->disk), &md->force_ro);
2354add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholmforce_ro_fail:
2355add710eaa88606de8ba98a014d37178579e6dbafJohan Rudholm	del_gendisk(md->disk);
2356371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2357371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	return ret;
2358371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin}
2359371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2360c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_SANDISK	0x2
2361c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_TOSHIBA	0x11
2362c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball#define CID_MANFID_MICRON	0x13
23633550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen#define CID_MANFID_SAMSUNG	0x15
2364c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball
23656f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentinstatic const struct mmc_fixup blk_fixups[] =
23666f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin{
2367c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
2368c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2369c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk,
2370c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2371c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk,
2372c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2373c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk,
2374c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2375c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk,
2376c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball		  MMC_QUIRK_INAND_CMD38),
2377d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin
2378d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	/*
2379d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * Some MMC cards experience performance degradation with CMD23
2380d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * instead of CMD12-bounded multiblock transfers. For now we'll
2381d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * black list what's bad...
2382d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * - Certain Toshiba cards.
2383d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 *
2384d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 * N.B. This doesn't affect SD cards.
2385d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin	 */
2386c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
2387d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
2388c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
2389d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
2390c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
2391d0c97cfb81ebc5b416c0f92fa2fc18d2773e3023Andrei Warkentin		  MMC_QUIRK_BLK_NO_CMD23),
23926de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK
23936de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	/*
23946de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 * Some Micron MMC cards needs longer data read timeout than
23956de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 * indicated in CSD.
23966de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK	 */
2397c59d44739a8519cb7abdcd7cb7fd88f807dec9fdChris Ball	MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
23986de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK		  MMC_QUIRK_LONG_READ_TIME),
23996de5fc9cf7de334912de4cfd2d06eb2d744d2afeStefan Nilsson XK
24003550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	/*
24013550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 * On these Samsung MoviNAND parts, performing secure erase or
24023550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 * secure trim can result in unrecoverable corruption due to a
24033550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 * firmware bug.
24043550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	 */
24053550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24063550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24073550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24083550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24093550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24103550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24113550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24123550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24133550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24143550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24153550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24163550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24173550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24183550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24193550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen	MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
24203550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
24213550ccdb9d8d350e526b809bf3dd92b550a74fe1Ian Chen
24226f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin	END_FIXUP
24236f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin};
24246f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin
24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_probe(struct mmc_card *card)
24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2427371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *md, *part_md;
2428a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman	char cap_str[10];
2429a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman
2430912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	/*
2431912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	 * Check that the card supports the command class(es) we need.
2432912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	 */
2433912490db699d83cb3d03570b63df7448677a3f56Pierre Ossman	if (!(card->csd.cmdclass & CCC_BLOCK_READ))
24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24365204d00f06ac9af4ef9c469cce7f9bbe179739b1Lukas Czerner	mmc_fixup_device(card, blk_fixups);
24375204d00f06ac9af4ef9c469cce7f9bbe179739b1Lukas Czerner
24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	md = mmc_blk_alloc(card);
24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(md))
24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return PTR_ERR(md);
24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2442444122fd58fdc83c96877a92b3f6288cafddb08dYi Li	string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
2443a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman			cap_str, sizeof(cap_str));
2444a3c76eb9d4a1e68a69dd880cf0bcb8a52418b993Girish K S	pr_info("%s: %s %s %s %s\n",
24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
2446a7bbb57333447d0cf950992653b6b079585f3531Pierre Ossman		cap_str, md->read_only ? "(ro)" : "");
24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2448371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_blk_alloc_parts(card, md))
2449371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
2450371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_set_drvdata(card, md);
24526f60c22252af05df94352240f30f9fc84090d88dAndrei Warkentin
2453371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	if (mmc_add_disk(md))
2454371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		goto out;
2455371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin
2456371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	list_for_each_entry(part_md, &md->part, part) {
2457371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		if (mmc_add_disk(part_md))
2458371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			goto out;
2459371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	}
2460e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson
2461e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_set_autosuspend_delay(&card->dev, 3000);
2462e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_use_autosuspend(&card->dev);
2463e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson
2464e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	/*
2465e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	 * Don't enable runtime PM for SD-combo cards here. Leave that
2466e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	 * decision to be taken during the SDIO init sequence instead.
2467e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	 */
2468e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	if (card->type != MMC_TYPE_SD_COMBO) {
2469e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		pm_runtime_set_active(&card->dev);
2470e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		pm_runtime_enable(&card->dev);
2471e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	}
2472e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson
24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
2476371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_parts(card, md);
2477371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_req(md);
24785865f2876baa5c68fd0d50029dd220ce19f3d2afUlf Hansson	return 0;
24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmc_blk_remove(struct mmc_card *card)
24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2485371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_parts(card, md);
2486e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_get_sync(&card->dev);
2487ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_claim_host(card->host);
2488ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_blk_part_switch(card, md);
2489ddd6fa7e794e62af3ec3eb4ffdc78489885701f2Adrian Hunter	mmc_release_host(card->host);
2490e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	if (card->type != MMC_TYPE_SD_COMBO)
2491e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson		pm_runtime_disable(&card->dev);
2492e94cfef698aae6b209d8918dd319312e4b02118dUlf Hansson	pm_runtime_put_noidle(&card->dev);
2493371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	mmc_blk_remove_req(md);
24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_set_drvdata(card, NULL);
24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24977628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic int _mmc_blk_suspend(struct mmc_card *card)
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2499371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_queue_suspend(&md->queue);
2504371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_for_each_entry(part_md, &md->part, part) {
2505371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			mmc_queue_suspend(&part_md->queue);
2506371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25117628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic void mmc_blk_shutdown(struct mmc_card *card)
25127628774851751e55362ec7d9d57c9334e656a655Ulf Hansson{
25137628774851751e55362ec7d9d57c9334e656a655Ulf Hansson	_mmc_blk_suspend(card);
25147628774851751e55362ec7d9d57c9334e656a655Ulf Hansson}
25157628774851751e55362ec7d9d57c9334e656a655Ulf Hansson
25167628774851751e55362ec7d9d57c9334e656a655Ulf Hansson#ifdef CONFIG_PM
25177628774851751e55362ec7d9d57c9334e656a655Ulf Hanssonstatic int mmc_blk_suspend(struct mmc_card *card)
25187628774851751e55362ec7d9d57c9334e656a655Ulf Hansson{
25197628774851751e55362ec7d9d57c9334e656a655Ulf Hansson	return _mmc_blk_suspend(card);
25207628774851751e55362ec7d9d57c9334e656a655Ulf Hansson}
25217628774851751e55362ec7d9d57c9334e656a655Ulf Hansson
25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmc_blk_resume(struct mmc_card *card)
25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2524371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin	struct mmc_blk_data *part_md;
25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_blk_data *md = mmc_get_drvdata(card);
25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (md) {
2528371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		/*
2529371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 * Resume involves the card going into idle state,
2530371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 * so current partition is always the main one.
2531371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		 */
2532371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		md->part_curr = md->part_type;
25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_queue_resume(&md->queue);
2534371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		list_for_each_entry(part_md, &md->part, part) {
2535371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin			mmc_queue_resume(&part_md->queue);
2536371a689f64b0da140c3bcd3f55305ffa1c3a58efAndrei Warkentin		}
25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	mmc_blk_suspend	NULL
25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmc_blk_resume	NULL
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mmc_driver mmc_driver = {
25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.drv		= {
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= "mmcblk",
25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= mmc_blk_probe,
25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.remove		= mmc_blk_remove,
25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= mmc_blk_suspend,
25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= mmc_blk_resume,
25537628774851751e55362ec7d9d57c9334e656a655Ulf Hansson	.shutdown	= mmc_blk_shutdown,
25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmc_blk_init(void)
25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25589d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	int res;
25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25605e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
25615e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson		pr_info("mmcblk: using %d minors per device\n", perdev_minors);
25625e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
25635e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson	max_devices = 256 / perdev_minors;
25645e71b7a64cb4c6cff75ca42b535d8227526ec592Olof Johansson
2565fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
2566fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	if (res)
25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25699d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	res = mmc_register_driver(&mmc_driver);
25709d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	if (res)
25719d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita		goto out2;
25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25739d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	return 0;
25749d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita out2:
25759d4e98e9609bc19d4a8ac4a5c3218358d1820114Akinobu Mita	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmc_blk_exit(void)
25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_unregister_driver(&mmc_driver);
2583fe6b4c8840c5e23fe9b8696450cee8f2e8cebffdPierre Ossman	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmc_blk_init);
25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmc_blk_exit);
25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2592