forked from Minki/linux
MMC core:
- Ensure that debugfs files are removed properly - Fix missing blk_put_request() - Deal with errors from blk_get_request() - Rewind mmc bus suspend operations at failures - Prepend '0x' to ocr and pre_eol_info in sysfs to identify as hex MMC host: - sdhci-msm: Make it optional to wait for signal level changes - sdhci: Avoid swiotlb buffer being full -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJaISyrAAoJEP4mhCVzWIwp84EP/RATcINow1f9vuIT1FJJ9vUl tAIo52Sx/9MEulLTGrfpbPSy0ZaEuNB+o5aMadXJ1YpQlkDkn760muTWA/widr4C eriBiBBR6UPI6zTItfgM4JqcrkW6qocEieNTe+mCk968PV0og16hRLMRV8ewlgJO QXnw5PrwDYRl6ejB3h1K8LDxyKfW1I7cV8GBluwwKc05wTO1vxcjbCyG2zD16zbz Yj7gbN2ttDMSvo9NpvFZFHBMeWWCvfOtlvU4uF5sxbLOmeF06oEJfQgLQnBWdh+j wYFuP5CCpzKcaXBMt+AcE8m+Re5oss+eZ7qkojReSh9Mr1iS+41tqjhzEXeD0Ck8 oS/tCsvNRkXuRjaRins7PQ2cDZ29822vv1kgM6RvHDGrSrTvyNc2jitWSFChjb2W ePue5eQQn7jM/C1ThDAt1uDWjIidovcSTCm4T7pFqV6Fy/090AMhY7HzyNjmTwc9 VkC7umZZt7RWnMS+6hhLLjyX2Oej9XTkLQ6gbiMp2RGpiTvdStqW6ohfUo4xb+9O 48tR24JjqCbbvTHpqX1agO5sL+R9rjGt7DRwLk+C3s6szpaAmuYyCLZXIIHQaQOY eH9oM8wW9iXK7LQR4tPcuuNjTmM4GOCslPMC0XfPdpcvujJwGRT8pjSI/ajPr7dP XVdvFhLS3kVMqvJR6rAn =13VJ -----END PGP SIGNATURE----- Merge tag 'mmc-v4.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC fixes from Ulf Hansson: "MMC core: - Ensure that debugfs files are removed properly - Fix missing blk_put_request() - Deal with errors from blk_get_request() - Rewind mmc bus suspend operations at failures - Prepend '0x' to ocr and pre_eol_info in sysfs to identify as hex MMC host: - sdhci-msm: Make it optional to wait for signal level changes - sdhci: Avoid swiotlb buffer being full" * tag 'mmc-v4.15-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: core: prepend 0x to OCR entry in sysfs mmc: core: prepend 0x to pre_eol_info entry in sysfs mmc: sdhci: Avoid swiotlb buffer being full mmc: sdhci-msm: Optionally wait for signal level changes mmc: block: Ensure that debugfs files are removed mmc: core: Do not leave the block driver in a suspended state mmc: block: Check return value of blk_get_request() mmc: block: Fix missing blk_put_request()
This commit is contained in:
commit
3c1c4ddffb
@ -122,6 +122,10 @@ struct mmc_blk_data {
|
||||
struct device_attribute force_ro;
|
||||
struct device_attribute power_ro_lock;
|
||||
int area_type;
|
||||
|
||||
/* debugfs files (only in main mmc_blk_data) */
|
||||
struct dentry *status_dentry;
|
||||
struct dentry *ext_csd_dentry;
|
||||
};
|
||||
|
||||
/* Device type for RPMB character devices */
|
||||
@ -233,9 +237,14 @@ static ssize_t power_ro_lock_store(struct device *dev,
|
||||
|
||||
/* Dispatch locking to the block layer */
|
||||
req = blk_get_request(mq->queue, REQ_OP_DRV_OUT, __GFP_RECLAIM);
|
||||
if (IS_ERR(req)) {
|
||||
count = PTR_ERR(req);
|
||||
goto out_put;
|
||||
}
|
||||
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
|
||||
blk_execute_rq(mq->queue, NULL, req, 0);
|
||||
ret = req_to_mmc_queue_req(req)->drv_op_result;
|
||||
blk_put_request(req);
|
||||
|
||||
if (!ret) {
|
||||
pr_info("%s: Locking boot partition ro until next power on\n",
|
||||
@ -248,7 +257,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
|
||||
set_disk_ro(part_md->disk, 1);
|
||||
}
|
||||
}
|
||||
|
||||
out_put:
|
||||
mmc_blk_put(md);
|
||||
return count;
|
||||
}
|
||||
@ -624,6 +633,10 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
|
||||
req = blk_get_request(mq->queue,
|
||||
idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
|
||||
__GFP_RECLAIM);
|
||||
if (IS_ERR(req)) {
|
||||
err = PTR_ERR(req);
|
||||
goto cmd_done;
|
||||
}
|
||||
idatas[0] = idata;
|
||||
req_to_mmc_queue_req(req)->drv_op =
|
||||
rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
|
||||
@ -691,6 +704,10 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
|
||||
req = blk_get_request(mq->queue,
|
||||
idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN,
|
||||
__GFP_RECLAIM);
|
||||
if (IS_ERR(req)) {
|
||||
err = PTR_ERR(req);
|
||||
goto cmd_err;
|
||||
}
|
||||
req_to_mmc_queue_req(req)->drv_op =
|
||||
rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
|
||||
req_to_mmc_queue_req(req)->drv_op_data = idata;
|
||||
@ -2550,6 +2567,8 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
|
||||
|
||||
/* Ask the block layer about the card status */
|
||||
req = blk_get_request(mq->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
|
||||
if (IS_ERR(req))
|
||||
return PTR_ERR(req);
|
||||
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
|
||||
blk_execute_rq(mq->queue, NULL, req, 0);
|
||||
ret = req_to_mmc_queue_req(req)->drv_op_result;
|
||||
@ -2557,6 +2576,7 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
|
||||
*val = ret;
|
||||
ret = 0;
|
||||
}
|
||||
blk_put_request(req);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2583,10 +2603,15 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
|
||||
|
||||
/* Ask the block layer for the EXT CSD */
|
||||
req = blk_get_request(mq->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
|
||||
if (IS_ERR(req)) {
|
||||
err = PTR_ERR(req);
|
||||
goto out_free;
|
||||
}
|
||||
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
|
||||
req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
|
||||
blk_execute_rq(mq->queue, NULL, req, 0);
|
||||
err = req_to_mmc_queue_req(req)->drv_op_result;
|
||||
blk_put_request(req);
|
||||
if (err) {
|
||||
pr_err("FAILED %d\n", err);
|
||||
goto out_free;
|
||||
@ -2632,7 +2657,7 @@ static const struct file_operations mmc_dbg_ext_csd_fops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int mmc_blk_add_debugfs(struct mmc_card *card)
|
||||
static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
|
||||
{
|
||||
struct dentry *root;
|
||||
|
||||
@ -2642,28 +2667,53 @@ static int mmc_blk_add_debugfs(struct mmc_card *card)
|
||||
root = card->debugfs_root;
|
||||
|
||||
if (mmc_card_mmc(card) || mmc_card_sd(card)) {
|
||||
if (!debugfs_create_file("status", S_IRUSR, root, card,
|
||||
&mmc_dbg_card_status_fops))
|
||||
md->status_dentry =
|
||||
debugfs_create_file("status", S_IRUSR, root, card,
|
||||
&mmc_dbg_card_status_fops);
|
||||
if (!md->status_dentry)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (mmc_card_mmc(card)) {
|
||||
if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
|
||||
&mmc_dbg_ext_csd_fops))
|
||||
md->ext_csd_dentry =
|
||||
debugfs_create_file("ext_csd", S_IRUSR, root, card,
|
||||
&mmc_dbg_ext_csd_fops);
|
||||
if (!md->ext_csd_dentry)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmc_blk_remove_debugfs(struct mmc_card *card,
|
||||
struct mmc_blk_data *md)
|
||||
{
|
||||
if (!card->debugfs_root)
|
||||
return;
|
||||
|
||||
if (!IS_ERR_OR_NULL(md->status_dentry)) {
|
||||
debugfs_remove(md->status_dentry);
|
||||
md->status_dentry = NULL;
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(md->ext_csd_dentry)) {
|
||||
debugfs_remove(md->ext_csd_dentry);
|
||||
md->ext_csd_dentry = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int mmc_blk_add_debugfs(struct mmc_card *card)
|
||||
static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmc_blk_remove_debugfs(struct mmc_card *card,
|
||||
struct mmc_blk_data *md)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static int mmc_blk_probe(struct mmc_card *card)
|
||||
@ -2703,7 +2753,7 @@ static int mmc_blk_probe(struct mmc_card *card)
|
||||
}
|
||||
|
||||
/* Add two debugfs entries */
|
||||
mmc_blk_add_debugfs(card);
|
||||
mmc_blk_add_debugfs(card, md);
|
||||
|
||||
pm_runtime_set_autosuspend_delay(&card->dev, 3000);
|
||||
pm_runtime_use_autosuspend(&card->dev);
|
||||
@ -2729,6 +2779,7 @@ static void mmc_blk_remove(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
|
||||
|
||||
mmc_blk_remove_debugfs(card, md);
|
||||
mmc_blk_remove_parts(card, md);
|
||||
pm_runtime_get_sync(&card->dev);
|
||||
mmc_claim_host(card->host);
|
||||
|
@ -157,6 +157,9 @@ static int mmc_bus_suspend(struct device *dev)
|
||||
return ret;
|
||||
|
||||
ret = host->bus_ops->suspend(host);
|
||||
if (ret)
|
||||
pm_generic_resume(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -314,4 +314,5 @@ err:
|
||||
void mmc_remove_card_debugfs(struct mmc_card *card)
|
||||
{
|
||||
debugfs_remove_recursive(card->debugfs_root);
|
||||
card->debugfs_root = NULL;
|
||||
}
|
||||
|
@ -781,7 +781,7 @@ MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
|
||||
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
|
||||
MMC_DEV_ATTR(prv, "0x%x\n", card->cid.prv);
|
||||
MMC_DEV_ATTR(rev, "0x%x\n", card->ext_csd.rev);
|
||||
MMC_DEV_ATTR(pre_eol_info, "%02x\n", card->ext_csd.pre_eol_info);
|
||||
MMC_DEV_ATTR(pre_eol_info, "0x%02x\n", card->ext_csd.pre_eol_info);
|
||||
MMC_DEV_ATTR(life_time, "0x%02x 0x%02x\n",
|
||||
card->ext_csd.device_life_time_est_typ_a,
|
||||
card->ext_csd.device_life_time_est_typ_b);
|
||||
@ -791,7 +791,7 @@ MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
|
||||
MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
|
||||
MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
|
||||
MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
|
||||
MMC_DEV_ATTR(ocr, "%08x\n", card->ocr);
|
||||
MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr);
|
||||
MMC_DEV_ATTR(cmdq_en, "%d\n", card->ext_csd.cmdq_en);
|
||||
|
||||
static ssize_t mmc_fwrev_show(struct device *dev,
|
||||
|
@ -675,7 +675,7 @@ MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
|
||||
MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
|
||||
MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
|
||||
MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
|
||||
MMC_DEV_ATTR(ocr, "%08x\n", card->ocr);
|
||||
MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr);
|
||||
|
||||
|
||||
static ssize_t mmc_dsr_show(struct device *dev,
|
||||
|
@ -29,6 +29,9 @@
|
||||
#define CORE_VERSION_MAJOR_MASK (0xf << CORE_VERSION_MAJOR_SHIFT)
|
||||
#define CORE_VERSION_MINOR_MASK 0xff
|
||||
|
||||
#define CORE_MCI_GENERICS 0x70
|
||||
#define SWITCHABLE_SIGNALING_VOLTAGE BIT(29)
|
||||
|
||||
#define CORE_HC_MODE 0x78
|
||||
#define HC_MODE_EN 0x1
|
||||
#define CORE_POWER 0x0
|
||||
@ -1028,11 +1031,22 @@ static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
|
||||
bool done = false;
|
||||
u32 val;
|
||||
|
||||
pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n",
|
||||
mmc_hostname(host->mmc), __func__, req_type,
|
||||
msm_host->curr_pwr_state, msm_host->curr_io_level);
|
||||
|
||||
/*
|
||||
* The power interrupt will not be generated for signal voltage
|
||||
* switches if SWITCHABLE_SIGNALING_VOLTAGE in MCI_GENERICS is not set.
|
||||
*/
|
||||
val = readl(msm_host->core_mem + CORE_MCI_GENERICS);
|
||||
if ((req_type & REQ_IO_HIGH || req_type & REQ_IO_LOW) &&
|
||||
!(val & SWITCHABLE_SIGNALING_VOLTAGE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IRQ for request type IO High/LOW will be generated when -
|
||||
* there is a state change in 1.8V enable bit (bit 3) of
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/swiotlb.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/of.h>
|
||||
@ -3650,17 +3651,6 @@ int sdhci_setup_host(struct sdhci_host *host)
|
||||
|
||||
spin_lock_init(&host->lock);
|
||||
|
||||
/*
|
||||
* Maximum number of segments. Depends on if the hardware
|
||||
* can do scatter/gather or not.
|
||||
*/
|
||||
if (host->flags & SDHCI_USE_ADMA)
|
||||
mmc->max_segs = SDHCI_MAX_SEGS;
|
||||
else if (host->flags & SDHCI_USE_SDMA)
|
||||
mmc->max_segs = 1;
|
||||
else /* PIO */
|
||||
mmc->max_segs = SDHCI_MAX_SEGS;
|
||||
|
||||
/*
|
||||
* Maximum number of sectors in one transfer. Limited by SDMA boundary
|
||||
* size (512KiB). Note some tuning modes impose a 4MiB limit, but this
|
||||
@ -3668,6 +3658,24 @@ int sdhci_setup_host(struct sdhci_host *host)
|
||||
*/
|
||||
mmc->max_req_size = 524288;
|
||||
|
||||
/*
|
||||
* Maximum number of segments. Depends on if the hardware
|
||||
* can do scatter/gather or not.
|
||||
*/
|
||||
if (host->flags & SDHCI_USE_ADMA) {
|
||||
mmc->max_segs = SDHCI_MAX_SEGS;
|
||||
} else if (host->flags & SDHCI_USE_SDMA) {
|
||||
mmc->max_segs = 1;
|
||||
if (swiotlb_max_segment()) {
|
||||
unsigned int max_req_size = (1 << IO_TLB_SHIFT) *
|
||||
IO_TLB_SEGSIZE;
|
||||
mmc->max_req_size = min(mmc->max_req_size,
|
||||
max_req_size);
|
||||
}
|
||||
} else { /* PIO */
|
||||
mmc->max_segs = SDHCI_MAX_SEGS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximum segment size. Could be one segment with the maximum number
|
||||
* of bytes. When doing hardware scatter/gather, each entry cannot
|
||||
|
Loading…
Reference in New Issue
Block a user