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:
Linus Torvalds 2017-12-01 08:14:22 -05:00
commit 3c1c4ddffb
7 changed files with 99 additions and 22 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -314,4 +314,5 @@ void mmc_add_card_debugfs(struct mmc_card *card)
void mmc_remove_card_debugfs(struct mmc_card *card)
{
debugfs_remove_recursive(card->debugfs_root);
card->debugfs_root = NULL;
}

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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