aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r--drivers/mmc/core/bus.c5
-rw-r--r--drivers/mmc/core/bus.h5
-rw-r--r--drivers/mmc/core/core.c10
-rw-r--r--drivers/mmc/core/core.h5
-rw-r--r--drivers/mmc/core/debugfs.c61
-rw-r--r--drivers/mmc/core/host.c5
-rw-r--r--drivers/mmc/core/host.h5
-rw-r--r--drivers/mmc/core/mmc.c11
-rw-r--r--drivers/mmc/core/mmc_test.c10
-rw-r--r--drivers/mmc/core/queue.c13
-rw-r--r--drivers/mmc/core/sd.c5
-rw-r--r--drivers/mmc/core/sdio.c105
-rw-r--r--drivers/mmc/core/sdio_io.c77
-rw-r--r--drivers/mmc/core/sdio_irq.c7
-rw-r--r--drivers/mmc/core/slot-gpio.c5
15 files changed, 159 insertions, 170 deletions
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index fc92c6c1c9a4..74de3f2dda38 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/drivers/mmc/core/bus.c
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright (C) 2007 Pierre Ossman
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
* MMC card bus driver model
*/
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h
index 72b0ef03f10a..8105852c4b62 100644
--- a/drivers/mmc/core/bus.h
+++ b/drivers/mmc/core/bus.h
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/drivers/mmc/core/bus.h
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright 2007 Pierre Ossman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#ifndef _MMC_CORE_BUS_H
#define _MMC_CORE_BUS_H
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 6db36dc870b5..221127324709 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/drivers/mmc/core/core.c
*
@@ -5,10 +6,6 @@
* SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
* Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
* MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -144,8 +141,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
int err = cmd->error;
/* Flag re-tuning needed on CRC errors */
- if ((cmd->opcode != MMC_SEND_TUNING_BLOCK &&
- cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
+ if (cmd->opcode != MMC_SEND_TUNING_BLOCK &&
+ cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 &&
+ !host->retune_crc_disable &&
(err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
(mrq->data && mrq->data->error == -EILSEQ) ||
(mrq->stop && mrq->stop->error == -EILSEQ)))
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index b5083b13d594..328c78dbee66 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/drivers/mmc/core/core.h
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright 2007 Pierre Ossman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#ifndef _MMC_CORE_CORE_H
#define _MMC_CORE_CORE_H
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index d2275c5a2311..09e0c7659469 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Debugfs support for hosts and cards
*
* Copyright (C) 2008 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/moduleparam.h>
#include <linux/export.h>
@@ -230,45 +227,21 @@ void mmc_add_host_debugfs(struct mmc_host *host)
struct dentry *root;
root = debugfs_create_dir(mmc_hostname(host), NULL);
- if (IS_ERR(root))
- /* Don't complain -- debugfs just isn't enabled */
- return;
- if (!root)
- /* Complain -- debugfs is enabled, but it failed to
- * create the directory. */
- goto err_root;
-
host->debugfs_root = root;
- if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops))
- goto err_node;
-
- if (!debugfs_create_x32("caps", S_IRUSR, root, &host->caps))
- goto err_node;
-
- if (!debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2))
- goto err_node;
-
- if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host,
- &mmc_clock_fops))
- goto err_node;
+ debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops);
+ debugfs_create_x32("caps", S_IRUSR, root, &host->caps);
+ debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2);
+ debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host,
+ &mmc_clock_fops);
#ifdef CONFIG_FAIL_MMC_REQUEST
if (fail_request)
setup_fault_attr(&fail_default_attr, fail_request);
host->fail_mmc_request = fail_default_attr;
- if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request",
- root,
- &host->fail_mmc_request)))
- goto err_node;
+ fault_create_debugfs_attr("fail_mmc_request", root,
+ &host->fail_mmc_request);
#endif
- return;
-
-err_node:
- debugfs_remove_recursive(root);
- host->debugfs_root = NULL;
-err_root:
- dev_err(&host->class_dev, "failed to initialize debugfs\n");
}
void mmc_remove_host_debugfs(struct mmc_host *host)
@@ -285,25 +258,9 @@ void mmc_add_card_debugfs(struct mmc_card *card)
return;
root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
- if (IS_ERR(root))
- /* Don't complain -- debugfs just isn't enabled */
- return;
- if (!root)
- /* Complain -- debugfs is enabled, but it failed to
- * create the directory. */
- goto err;
-
card->debugfs_root = root;
- if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
- goto err;
-
- return;
-
-err:
- debugfs_remove_recursive(root);
- card->debugfs_root = NULL;
- dev_err(&card->dev, "failed to initialize debugfs\n");
+ debugfs_create_x32("state", S_IRUSR, root, &card->state);
}
void mmc_remove_card_debugfs(struct mmc_card *card)
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 6a51f7a06ce7..105b7a7c0251 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/drivers/mmc/core/host.c
*
@@ -5,10 +6,6 @@
* Copyright (C) 2007-2008 Pierre Ossman
* Copyright (C) 2010 Linus Walleij
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
* MMC host class device management
*/
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index 4805438c02ff..5e3b9534ffb2 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/drivers/mmc/core/host.h
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright 2007 Pierre Ossman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#ifndef _MMC_CORE_HOST_H
#define _MMC_CORE_HOST_H
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 3e786ba204c3..c8804895595f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/drivers/mmc/core/mmc.c
*
* Copyright (C) 2003-2004 Russell King, All Rights Reserved.
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
* MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/err.h>
@@ -1212,13 +1209,13 @@ static int mmc_select_hs400(struct mmc_card *card)
mmc_set_timing(host, MMC_TIMING_MMC_HS400);
mmc_set_bus_speed(card);
+ if (host->ops->hs400_complete)
+ host->ops->hs400_complete(host);
+
err = mmc_switch_status(card);
if (err)
goto out_err;
- if (host->ops->hs400_complete)
- host->ops->hs400_complete(host);
-
return 0;
out_err:
diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c
index b27df2d2b5ae..492dd4596314 100644
--- a/drivers/mmc/core/mmc_test.c
+++ b/drivers/mmc/core/mmc_test.c
@@ -3167,15 +3167,7 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
struct mmc_test_dbgfs_file *df;
if (card->debugfs_root)
- file = debugfs_create_file(name, mode, card->debugfs_root,
- card, fops);
-
- if (IS_ERR_OR_NULL(file)) {
- dev_err(&card->dev,
- "Can't create %s. Perhaps debugfs is disabled.\n",
- name);
- return -ENODEV;
- }
+ debugfs_create_file(name, mode, card->debugfs_root, card, fops);
df = kmalloc(sizeof(*df), GFP_KERNEL);
if (!df) {
diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
index 92900a095796..e327f80ebe70 100644
--- a/drivers/mmc/core/queue.c
+++ b/drivers/mmc/core/queue.c
@@ -1,11 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2003 Russell King, All Rights Reserved.
* Copyright 2006-2007 Pierre Ossman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
*/
#include <linux/slab.h>
#include <linux/module.h>
@@ -354,18 +350,15 @@ static const struct blk_mq_ops mmc_mq_ops = {
static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card)
{
struct mmc_host *host = card->host;
- u64 limit = BLK_BOUNCE_HIGH;
unsigned block_size = 512;
- if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
- limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
-
blk_queue_flag_set(QUEUE_FLAG_NONROT, mq->queue);
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, mq->queue);
if (mmc_can_erase(card))
mmc_queue_setup_discard(mq->queue, card);
- blk_queue_bounce_limit(mq->queue, limit);
+ if (!mmc_dev(host)->dma_mask || !*mmc_dev(host)->dma_mask)
+ blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
blk_queue_max_hw_sectors(mq->queue,
min(host->max_blk_count, host->max_req_size / 512));
blk_queue_max_segments(mq->queue, host->max_segs);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index d3d32f9a2cb1..d681e8aaca83 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/drivers/mmc/core/sd.c
*
* Copyright (C) 2003-2004 Russell King, All Rights Reserved.
* SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
* Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/err.h>
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index d1aa1c7577bb..8dd8fc32ecca 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -559,7 +559,7 @@ static void mmc_sdio_resend_if_cond(struct mmc_host *host,
* we're trying to reinitialise.
*/
static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
- struct mmc_card *oldcard, int powered_resume)
+ struct mmc_card *oldcard)
{
struct mmc_card *card;
int err;
@@ -582,11 +582,9 @@ try_again:
/*
* Inform the card of the voltage
*/
- if (!powered_resume) {
- err = mmc_send_io_op_cond(host, ocr, &rocr);
- if (err)
- goto err;
- }
+ err = mmc_send_io_op_cond(host, ocr, &rocr);
+ if (err)
+ goto err;
/*
* For SPI, enable CRC as appropriate.
@@ -645,7 +643,7 @@ try_again:
* try to init uhs card. sdio_read_cccr will take over this task
* to make sure which speed mode should work.
*/
- if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
+ if (rocr & ocr & R4_18V_PRESENT) {
err = mmc_set_uhs_voltage(host, ocr_card);
if (err == -EAGAIN) {
mmc_sdio_resend_if_cond(host, card);
@@ -659,7 +657,7 @@ try_again:
/*
* For native busses: set card RCA and quit open drain mode.
*/
- if (!powered_resume && !mmc_host_is_spi(host)) {
+ if (!mmc_host_is_spi(host)) {
err = mmc_send_relative_addr(host, &card->rca);
if (err)
goto remove;
@@ -687,7 +685,7 @@ try_again:
/*
* Select card, as all following commands rely on that.
*/
- if (!powered_resume && !mmc_host_is_spi(host)) {
+ if (!mmc_host_is_spi(host)) {
err = mmc_select_card(card);
if (err)
goto remove;
@@ -816,10 +814,27 @@ err:
return err;
}
-static int mmc_sdio_reinit_card(struct mmc_host *host, bool powered_resume)
+static int mmc_sdio_reinit_card(struct mmc_host *host)
{
int ret;
+ /*
+ * Reset the card by performing the same steps that are taken by
+ * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe.
+ *
+ * sdio_reset() is technically not needed. Having just powered up the
+ * hardware, it should already be in reset state. However, some
+ * platforms (such as SD8686 on OLPC) do not instantly cut power,
+ * meaning that a reset is required when restoring power soon after
+ * powering off. It is harmless in other cases.
+ *
+ * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec,
+ * is not necessary for non-removable cards. However, it is required
+ * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and
+ * harmless in other situations.
+ *
+ */
+
sdio_reset(host);
mmc_go_idle(host);
mmc_send_if_cond(host, host->card->ocr);
@@ -828,8 +843,7 @@ static int mmc_sdio_reinit_card(struct mmc_host *host, bool powered_resume)
if (ret)
return ret;
- return mmc_sdio_init_card(host, host->card->ocr, host->card,
- powered_resume);
+ return mmc_sdio_init_card(host, host->card->ocr, host->card);
}
/*
@@ -937,6 +951,10 @@ static int mmc_sdio_pre_suspend(struct mmc_host *host)
*/
static int mmc_sdio_suspend(struct mmc_host *host)
{
+ /* Prevent processing of SDIO IRQs in suspended state. */
+ mmc_card_set_suspended(host->card);
+ cancel_delayed_work_sync(&host->sdio_irq_work);
+
mmc_claim_host(host);
if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host))
@@ -961,7 +979,11 @@ static int mmc_sdio_resume(struct mmc_host *host)
/* Basic card reinitialization. */
mmc_claim_host(host);
- /* Restore power if needed */
+ /*
+ * Restore power and reinitialize the card when needed. Note that a
+ * removable card is checked from a detect work later on in the resume
+ * process.
+ */
if (!mmc_card_keep_power(host)) {
mmc_power_up(host, host->card->ocr);
/*
@@ -975,61 +997,32 @@ static int mmc_sdio_resume(struct mmc_host *host)
pm_runtime_set_active(&host->card->dev);
pm_runtime_enable(&host->card->dev);
}
- }
-
- /* No need to reinitialize powered-resumed nonremovable cards */
- if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) {
- err = mmc_sdio_reinit_card(host, mmc_card_keep_power(host));
- } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
+ err = mmc_sdio_reinit_card(host);
+ } else if (mmc_card_wake_sdio_irq(host)) {
/* We may have switched to 1-bit mode during suspend */
err = sdio_enable_4bit_bus(host->card);
}
- if (!err && host->sdio_irqs) {
+ if (err)
+ goto out;
+
+ /* Allow SDIO IRQs to be processed again. */
+ mmc_card_clr_suspended(host->card);
+
+ if (host->sdio_irqs) {
if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD))
wake_up_process(host->sdio_irq_thread);
else if (host->caps & MMC_CAP_SDIO_IRQ)
host->ops->enable_sdio_irq(host, 1);
}
+out:
mmc_release_host(host);
host->pm_flags &= ~MMC_PM_KEEP_POWER;
return err;
}
-static int mmc_sdio_power_restore(struct mmc_host *host)
-{
- int ret;
-
- /*
- * Reset the card by performing the same steps that are taken by
- * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe.
- *
- * sdio_reset() is technically not needed. Having just powered up the
- * hardware, it should already be in reset state. However, some
- * platforms (such as SD8686 on OLPC) do not instantly cut power,
- * meaning that a reset is required when restoring power soon after
- * powering off. It is harmless in other cases.
- *
- * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec,
- * is not necessary for non-removable cards. However, it is required
- * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and
- * harmless in other situations.
- *
- */
-
- mmc_claim_host(host);
-
- ret = mmc_sdio_reinit_card(host, mmc_card_keep_power(host));
- if (!ret && host->sdio_irqs)
- mmc_signal_sdio_irq(host);
-
- mmc_release_host(host);
-
- return ret;
-}
-
static int mmc_sdio_runtime_suspend(struct mmc_host *host)
{
/* No references to the card, cut the power to it. */
@@ -1047,7 +1040,7 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host)
/* Restore power and re-initialize. */
mmc_claim_host(host);
mmc_power_up(host, host->card->ocr);
- ret = mmc_sdio_power_restore(host);
+ ret = mmc_sdio_reinit_card(host);
mmc_release_host(host);
return ret;
@@ -1056,7 +1049,7 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host)
static int mmc_sdio_hw_reset(struct mmc_host *host)
{
mmc_power_cycle(host, host->card->ocr);
- return mmc_sdio_power_restore(host);
+ return mmc_sdio_reinit_card(host);
}
static int mmc_sdio_sw_reset(struct mmc_host *host)
@@ -1068,7 +1061,7 @@ static int mmc_sdio_sw_reset(struct mmc_host *host)
mmc_set_initial_state(host);
mmc_set_initial_signal_voltage(host);
- return mmc_sdio_reinit_card(host, 0);
+ return mmc_sdio_reinit_card(host);
}
static const struct mmc_bus_ops mmc_sdio_ops = {
@@ -1118,7 +1111,7 @@ int mmc_attach_sdio(struct mmc_host *host)
/*
* Detect and init the card.
*/
- err = mmc_sdio_init_card(host, rocr, NULL, 0);
+ err = mmc_sdio_init_card(host, rocr, NULL);
if (err)
goto err;
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index f79f0b0caab8..2ba00acf64e6 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -15,6 +15,7 @@
#include "sdio_ops.h"
#include "core.h"
#include "card.h"
+#include "host.h"
/**
* sdio_claim_host - exclusively claim a bus for a certain SDIO function
@@ -734,3 +735,79 @@ int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags)
return 0;
}
EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags);
+
+/**
+ * sdio_retune_crc_disable - temporarily disable retuning on CRC errors
+ * @func: SDIO function attached to host
+ *
+ * If the SDIO card is known to be in a state where it might produce
+ * CRC errors on the bus in response to commands (like if we know it is
+ * transitioning between power states), an SDIO function driver can
+ * call this function to temporarily disable the SD/MMC core behavior of
+ * triggering an automatic retuning.
+ *
+ * This function should be called while the host is claimed and the host
+ * should remain claimed until sdio_retune_crc_enable() is called.
+ * Specifically, the expected sequence of calls is:
+ * - sdio_claim_host()
+ * - sdio_retune_crc_disable()
+ * - some number of calls like sdio_writeb() and sdio_readb()
+ * - sdio_retune_crc_enable()
+ * - sdio_release_host()
+ */
+void sdio_retune_crc_disable(struct sdio_func *func)
+{
+ func->card->host->retune_crc_disable = true;
+}
+EXPORT_SYMBOL_GPL(sdio_retune_crc_disable);
+
+/**
+ * sdio_retune_crc_enable - re-enable retuning on CRC errors
+ * @func: SDIO function attached to host
+ *
+ * This is the compement to sdio_retune_crc_disable().
+ */
+void sdio_retune_crc_enable(struct sdio_func *func)
+{
+ func->card->host->retune_crc_disable = false;
+}
+EXPORT_SYMBOL_GPL(sdio_retune_crc_enable);
+
+/**
+ * sdio_retune_hold_now - start deferring retuning requests till release
+ * @func: SDIO function attached to host
+ *
+ * This function can be called if it's currently a bad time to do
+ * a retune of the SDIO card. Retune requests made during this time
+ * will be held and we'll actually do the retune sometime after the
+ * release.
+ *
+ * This function could be useful if an SDIO card is in a power state
+ * where it can respond to a small subset of commands that doesn't
+ * include the retuning command. Care should be taken when using
+ * this function since (presumably) the retuning request we might be
+ * deferring was made for a good reason.
+ *
+ * This function should be called while the host is claimed.
+ */
+void sdio_retune_hold_now(struct sdio_func *func)
+{
+ mmc_retune_hold_now(func->card->host);
+}
+EXPORT_SYMBOL_GPL(sdio_retune_hold_now);
+
+/**
+ * sdio_retune_release - signal that it's OK to retune now
+ * @func: SDIO function attached to host
+ *
+ * This is the complement to sdio_retune_hold_now(). Calling this
+ * function won't make a retune happen right away but will allow
+ * them to be scheduled normally.
+ *
+ * This function should be called while the host is claimed.
+ */
+void sdio_retune_release(struct sdio_func *func)
+{
+ mmc_retune_release(func->card->host);
+}
+EXPORT_SYMBOL_GPL(sdio_retune_release);
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 931e6226c0b3..0bcc5e83bd1a 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -34,6 +34,10 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
unsigned char pending;
struct sdio_func *func;
+ /* Don't process SDIO IRQs if the card is suspended. */
+ if (mmc_card_suspended(card))
+ return 0;
+
/*
* Optimization, if there is only 1 function interrupt registered
* and we know an IRQ was signaled then call irq handler directly.
@@ -88,7 +92,7 @@ static int process_sdio_pending_irqs(struct mmc_host *host)
return ret;
}
-void sdio_run_irqs(struct mmc_host *host)
+static void sdio_run_irqs(struct mmc_host *host)
{
mmc_claim_host(host);
if (host->sdio_irqs) {
@@ -99,7 +103,6 @@ void sdio_run_irqs(struct mmc_host *host)
}
mmc_release_host(host);
}
-EXPORT_SYMBOL_GPL(sdio_run_irqs);
void sdio_irq_work(struct work_struct *work)
{
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 4afc6b87b465..da2596c5fa28 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Generic GPIO card-detect helper
*
* Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/err.h>