aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2020-09-09 18:26:07 +0200
committerTakashi Iwai <tiwai@suse.de>2020-09-09 18:26:48 +0200
commit9ddb236f13594b34a12dacf69a5adca7a1aef35e (patch)
tree1dc1f6e54962a2e3ad3d56c894522cb4b1ddce93 /drivers/mmc/core
parentALSA: vx: vx_pcm: remove redundant assignment (diff)
parentALSA: hda/realtek - The Mic on a RedmiBook doesn't work (diff)
downloadlinux-dev-9ddb236f13594b34a12dacf69a5adca7a1aef35e.tar.xz
linux-dev-9ddb236f13594b34a12dacf69a5adca7a1aef35e.zip
Merge branch 'for-linus' into for-next
Back-merge to apply the tasklet conversion patches that are based on the already applied tasklet API changes on 5.9-rc4. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/block.c11
-rw-r--r--drivers/mmc/core/core.c11
-rw-r--r--drivers/mmc/core/host.c6
-rw-r--r--drivers/mmc/core/mmc.c3
-rw-r--r--drivers/mmc/core/queue.c2
-rw-r--r--drivers/mmc/core/quirks.h6
-rw-r--r--drivers/mmc/core/regulator.c2
-rw-r--r--drivers/mmc/core/sdio.c64
-rw-r--r--drivers/mmc/core/sdio_io.c3
-rw-r--r--drivers/mmc/core/sdio_irq.c3
10 files changed, 68 insertions, 43 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 7896952de1ac..fa313b634135 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -312,10 +312,7 @@ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
mutex_lock(&block_mutex);
if (md) {
- if (md->usage == 2)
- check_disk_change(bdev);
ret = 0;
-
if ((mode & FMODE_WRITE) && md->read_only) {
mmc_blk_put(md);
ret = -EROFS;
@@ -1446,7 +1443,7 @@ static void mmc_blk_cqe_req_done(struct mmc_request *mrq)
*/
if (mq->in_recovery)
mmc_blk_cqe_complete_rq(mq, req);
- else
+ else if (likely(!blk_should_fake_timeout(req->q)))
blk_mq_complete_request(req);
}
@@ -1926,7 +1923,7 @@ static void mmc_blk_hsq_req_done(struct mmc_request *mrq)
*/
if (mq->in_recovery)
mmc_blk_cqe_complete_rq(mq, req);
- else
+ else if (likely(!blk_should_fake_timeout(req->q)))
blk_mq_complete_request(req);
}
@@ -1936,7 +1933,7 @@ void mmc_blk_mq_complete(struct request *req)
if (mq->use_cqe)
mmc_blk_cqe_complete_rq(mq, req);
- else
+ else if (likely(!blk_should_fake_timeout(req->q)))
mmc_blk_mq_complete_rq(mq, req);
}
@@ -1988,7 +1985,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req)
*/
if (mq->in_recovery)
mmc_blk_mq_complete_rq(mq, req);
- else
+ else if (likely(!blk_should_fake_timeout(req->q)))
blk_mq_complete_request(req);
mmc_blk_mq_dec_in_flight(mq, req);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 8d2b808e9b58..8ccae6452b9c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1455,12 +1455,12 @@ void mmc_detach_bus(struct mmc_host *host)
void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq)
{
/*
- * If the device is configured as wakeup, we prevent a new sleep for
- * 5 s to give provision for user space to consume the event.
+ * Prevent system sleep for 5s to allow user space to consume the
+ * corresponding uevent. This is especially useful, when CD irq is used
+ * as a system wakeup, but doesn't hurt in other cases.
*/
- if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) &&
- device_can_wakeup(mmc_dev(host)))
- pm_wakeup_event(mmc_dev(host), 5000);
+ if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL))
+ __pm_wakeup_event(host->ws, 5000);
host->detect_change = 1;
mmc_schedule_delayed_work(&host->detect, delay);
@@ -2303,7 +2303,6 @@ void mmc_start_host(struct mmc_host *host)
{
host->f_init = max(min(freqs[0], host->f_max), host->f_min);
host->rescan_disable = 0;
- host->ios.power_mode = MMC_POWER_UNDEFINED;
if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) {
mmc_claim_host(host);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index c8768726d925..ce43f7573d80 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -15,6 +15,7 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/pagemap.h>
+#include <linux/pm_wakeup.h>
#include <linux/export.h>
#include <linux/leds.h>
#include <linux/slab.h>
@@ -36,6 +37,7 @@ static DEFINE_IDA(mmc_host_ida);
static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ wakeup_source_unregister(host->ws);
ida_simple_remove(&mmc_host_ida, host->index);
kfree(host);
}
@@ -275,6 +277,8 @@ int mmc_of_parse(struct mmc_host *host)
host->caps |= MMC_CAP_SDIO_IRQ;
if (device_property_read_bool(dev, "full-pwr-cycle"))
host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
+ if (device_property_read_bool(dev, "full-pwr-cycle-in-suspend"))
+ host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND;
if (device_property_read_bool(dev, "keep-power-in-suspend"))
host->pm_caps |= MMC_PM_KEEP_POWER;
if (device_property_read_bool(dev, "wakeup-source") ||
@@ -400,6 +404,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
host->index = err;
dev_set_name(&host->class_dev, "mmc%d", host->index);
+ host->ws = wakeup_source_register(NULL, dev_name(&host->class_dev));
host->parent = dev;
host->class_dev.parent = dev;
@@ -431,6 +436,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
host->fixed_drv_type = -EINVAL;
host->ios.power_delay_ms = 10;
+ host->ios.power_mode = MMC_POWER_UNDEFINED;
return host;
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 4203303f946a..b3fa193de846 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2038,7 +2038,8 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
goto out;
if (mmc_can_poweroff_notify(host->card) &&
- ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend))
+ ((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend ||
+ (host->caps2 & MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND)))
err = mmc_poweroff_notify(host->card, notify_type);
else if (mmc_can_sleep(host->card))
err = mmc_sleep(host);
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index 4b1eb89b401d..6c022ef0f84d 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -203,7 +203,7 @@ static unsigned int mmc_get_max_segments(struct mmc_host *host)
/**
* mmc_init_request() - initialize the MMC-specific per-request data
- * @q: the request queue
+ * @mq: the request queue
* @req: the request
* @gfp: memory allocation policy
*/
diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h
index 472fa2fdcf13..d68e6e513a4f 100644
--- a/drivers/mmc/core/quirks.h
+++ b/drivers/mmc/core/quirks.h
@@ -14,7 +14,7 @@
#include "card.h"
-static const struct mmc_fixup mmc_blk_fixups[] = {
+static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
#define INAND_CMD38_ARG_EXT_CSD 113
#define INAND_CMD38_ARG_ERASE 0x00
#define INAND_CMD38_ARG_TRIM 0x01
@@ -102,7 +102,7 @@ static const struct mmc_fixup mmc_blk_fixups[] = {
END_FIXUP
};
-static const struct mmc_fixup mmc_ext_csd_fixups[] = {
+static const struct mmc_fixup __maybe_unused mmc_ext_csd_fixups[] = {
/*
* Certain Hynix eMMC 4.41 cards might get broken when HPI feature
* is used so disable the HPI feature for such buggy cards.
@@ -120,7 +120,7 @@ static const struct mmc_fixup mmc_ext_csd_fixups[] = {
};
-static const struct mmc_fixup sdio_fixup_methods[] = {
+static const struct mmc_fixup __maybe_unused sdio_fixup_methods[] = {
SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251,
add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c
index 96b1d15045d6..609201a467ef 100644
--- a/drivers/mmc/core/regulator.c
+++ b/drivers/mmc/core/regulator.c
@@ -159,6 +159,8 @@ static int mmc_regulator_set_voltage_if_supported(struct regulator *regulator,
/**
* mmc_regulator_set_vqmmc - Set VQMMC as per the ios
+ * @mmc: the host to regulate
+ * @ios: io bus settings
*
* For 3.3V signaling, we try to match VQMMC to VMMC as closely as possible.
* That will match the behavior of old boards where VQMMC and VMMC were supplied
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index b65b26f76d71..7b40553d3934 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -176,15 +176,18 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr)
if (mmc_host_uhs(card->host)) {
if (data & SDIO_UHS_DDR50)
card->sw_caps.sd3_bus_mode
- |= SD_MODE_UHS_DDR50;
+ |= SD_MODE_UHS_DDR50 | SD_MODE_UHS_SDR50
+ | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12;
if (data & SDIO_UHS_SDR50)
card->sw_caps.sd3_bus_mode
- |= SD_MODE_UHS_SDR50;
+ |= SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR25
+ | SD_MODE_UHS_SDR12;
if (data & SDIO_UHS_SDR104)
card->sw_caps.sd3_bus_mode
- |= SD_MODE_UHS_SDR104;
+ |= SD_MODE_UHS_SDR104 | SD_MODE_UHS_SDR50
+ | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12;
}
ret = mmc_io_rw_direct(card, 0, 0,
@@ -303,30 +306,49 @@ static int sdio_disable_wide(struct mmc_card *card)
return 0;
}
+static int sdio_disable_4bit_bus(struct mmc_card *card)
+{
+ int err;
+
+ if (card->type == MMC_TYPE_SDIO)
+ goto out;
+
+ if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
+ return 0;
+
+ if (!(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4))
+ return 0;
+
+ err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1);
+ if (err)
+ return err;
+
+out:
+ return sdio_disable_wide(card);
+}
+
static int sdio_enable_4bit_bus(struct mmc_card *card)
{
int err;
+ err = sdio_enable_wide(card);
+ if (err <= 0)
+ return err;
if (card->type == MMC_TYPE_SDIO)
- err = sdio_enable_wide(card);
- else if ((card->host->caps & MMC_CAP_4_BIT_DATA) &&
- (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
+ goto out;
+
+ if (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4) {
err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
- if (err)
+ if (err) {
+ sdio_disable_wide(card);
return err;
- err = sdio_enable_wide(card);
- if (err <= 0)
- mmc_app_set_bus_width(card, MMC_BUS_WIDTH_1);
- } else
- return 0;
-
- if (err > 0) {
- mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
- err = 0;
+ }
}
+out:
+ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
- return err;
+ return 0;
}
@@ -518,10 +540,8 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)
max_rate = min_not_zero(card->quirk_max_rate,
card->sw_caps.uhs_max_dtr);
- if (bus_speed) {
- mmc_set_timing(card->host, timing);
- mmc_set_clock(card->host, max_rate);
- }
+ mmc_set_timing(card->host, timing);
+ mmc_set_clock(card->host, max_rate);
return 0;
}
@@ -972,7 +992,7 @@ static int mmc_sdio_suspend(struct mmc_host *host)
mmc_claim_host(host);
if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host))
- sdio_disable_wide(host->card);
+ sdio_disable_4bit_bus(host->card);
if (!mmc_card_keep_power(host)) {
mmc_power_off(host);
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index 2ba00acf64e6..79dbf90216b5 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -133,7 +133,7 @@ int sdio_disable_func(struct sdio_func *func)
err:
pr_debug("SDIO: Failed to disable device %s\n", sdio_func_id(func));
- return -EIO;
+ return ret;
}
EXPORT_SYMBOL_GPL(sdio_disable_func);
@@ -709,6 +709,7 @@ EXPORT_SYMBOL_GPL(sdio_get_host_pm_caps);
/**
* sdio_set_host_pm_flags - set wanted host power management capabilities
* @func: SDIO function attached to host
+ * @flags: Power Management flags to set
*
* Set a capability bitmask corresponding to wanted host controller
* power management features for the upcoming suspend state.
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 3ffe4ff49aa7..4b1f7c966ec8 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -139,11 +139,10 @@ EXPORT_SYMBOL_GPL(sdio_signal_irq);
static int sdio_irq_thread(void *_host)
{
struct mmc_host *host = _host;
- struct sched_param param = { .sched_priority = 1 };
unsigned long period, idle_period;
int ret;
- sched_setscheduler(current, SCHED_FIFO, &param);
+ sched_set_fifo_low(current);
/*
* We want to allow for SDIO cards to work even on non SDIO