Skip to content

Commit 627c3cc

Browse files
Linus Walleijstorulf
authored andcommitted
mmc: debugfs: Move block debugfs into block module
If we don't have the block layer enabled, we do not present card status and extcsd in the debugfs. Debugfs is not ABI, and maintaining files of no relevance for non-block devices comes at a high maintenance cost if we shall support it with the block layer compiled out. The debugfs entries suffer from all the same starvation issues as the other userspace things, under e.g. a heavy dd operation. The expected number of debugfs users utilizing these two debugfs files is already low as there is an ioctl() to get the same information using the mmc-tools, and of these few users the expected number of people using it on SDIO or combo cards are expected to be zero. It is therefore logical to move this over to the block layer when it is enabled, using the new custom requests and issue it using the block request queue. On the other hand it moves some debugfs code from debugfs.c and into block.c. Tested during heavy dd load by cat:in the status file. Signed-off-by: Linus Walleij <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent 1bee324 commit 627c3cc

File tree

3 files changed

+147
-89
lines changed

3 files changed

+147
-89
lines changed

drivers/mmc/core/block.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/compat.h>
3737
#include <linux/pm_runtime.h>
3838
#include <linux/idr.h>
39+
#include <linux/debugfs.h>
3940

4041
#include <linux/mmc/ioctl.h>
4142
#include <linux/mmc/card.h>
@@ -1177,6 +1178,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
11771178
struct mmc_card *card = mq->card;
11781179
struct mmc_blk_data *md = mq->blkdata;
11791180
struct mmc_blk_ioc_data **idata;
1181+
u8 **ext_csd;
1182+
u32 status;
11801183
int ret;
11811184
int i;
11821185

@@ -1206,6 +1209,15 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
12061209
card->ext_csd.boot_ro_lock |=
12071210
EXT_CSD_BOOT_WP_B_PWR_WP_EN;
12081211
break;
1212+
case MMC_DRV_OP_GET_CARD_STATUS:
1213+
ret = mmc_send_status(card, &status);
1214+
if (!ret)
1215+
ret = status;
1216+
break;
1217+
case MMC_DRV_OP_GET_EXT_CSD:
1218+
ext_csd = mq_rq->drv_op_data;
1219+
ret = mmc_get_ext_csd(card, ext_csd);
1220+
break;
12091221
default:
12101222
pr_err("%s: unknown driver specific operation\n",
12111223
md->disk->disk_name);
@@ -2283,6 +2295,134 @@ static int mmc_add_disk(struct mmc_blk_data *md)
22832295
return ret;
22842296
}
22852297

2298+
#ifdef CONFIG_DEBUG_FS
2299+
2300+
static int mmc_dbg_card_status_get(void *data, u64 *val)
2301+
{
2302+
struct mmc_card *card = data;
2303+
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
2304+
struct mmc_queue *mq = &md->queue;
2305+
struct request *req;
2306+
int ret;
2307+
2308+
/* Ask the block layer about the card status */
2309+
req = blk_get_request(mq->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
2310+
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
2311+
blk_execute_rq(mq->queue, NULL, req, 0);
2312+
ret = req_to_mmc_queue_req(req)->drv_op_result;
2313+
if (ret >= 0) {
2314+
*val = ret;
2315+
ret = 0;
2316+
}
2317+
2318+
return ret;
2319+
}
2320+
DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
2321+
NULL, "%08llx\n");
2322+
2323+
/* That is two digits * 512 + 1 for newline */
2324+
#define EXT_CSD_STR_LEN 1025
2325+
2326+
static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
2327+
{
2328+
struct mmc_card *card = inode->i_private;
2329+
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
2330+
struct mmc_queue *mq = &md->queue;
2331+
struct request *req;
2332+
char *buf;
2333+
ssize_t n = 0;
2334+
u8 *ext_csd;
2335+
int err, i;
2336+
2337+
buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
2338+
if (!buf)
2339+
return -ENOMEM;
2340+
2341+
/* Ask the block layer for the EXT CSD */
2342+
req = blk_get_request(mq->queue, REQ_OP_DRV_IN, __GFP_RECLAIM);
2343+
req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
2344+
req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
2345+
blk_execute_rq(mq->queue, NULL, req, 0);
2346+
err = req_to_mmc_queue_req(req)->drv_op_result;
2347+
if (err) {
2348+
pr_err("FAILED %d\n", err);
2349+
goto out_free;
2350+
}
2351+
2352+
for (i = 0; i < 512; i++)
2353+
n += sprintf(buf + n, "%02x", ext_csd[i]);
2354+
n += sprintf(buf + n, "\n");
2355+
2356+
if (n != EXT_CSD_STR_LEN) {
2357+
err = -EINVAL;
2358+
goto out_free;
2359+
}
2360+
2361+
filp->private_data = buf;
2362+
kfree(ext_csd);
2363+
return 0;
2364+
2365+
out_free:
2366+
kfree(buf);
2367+
return err;
2368+
}
2369+
2370+
static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
2371+
size_t cnt, loff_t *ppos)
2372+
{
2373+
char *buf = filp->private_data;
2374+
2375+
return simple_read_from_buffer(ubuf, cnt, ppos,
2376+
buf, EXT_CSD_STR_LEN);
2377+
}
2378+
2379+
static int mmc_ext_csd_release(struct inode *inode, struct file *file)
2380+
{
2381+
kfree(file->private_data);
2382+
return 0;
2383+
}
2384+
2385+
static const struct file_operations mmc_dbg_ext_csd_fops = {
2386+
.open = mmc_ext_csd_open,
2387+
.read = mmc_ext_csd_read,
2388+
.release = mmc_ext_csd_release,
2389+
.llseek = default_llseek,
2390+
};
2391+
2392+
static int mmc_blk_add_debugfs(struct mmc_card *card)
2393+
{
2394+
struct dentry *root;
2395+
2396+
if (!card->debugfs_root)
2397+
return 0;
2398+
2399+
root = card->debugfs_root;
2400+
2401+
if (mmc_card_mmc(card) || mmc_card_sd(card)) {
2402+
if (!debugfs_create_file("status", S_IRUSR, root, card,
2403+
&mmc_dbg_card_status_fops))
2404+
return -EIO;
2405+
}
2406+
2407+
if (mmc_card_mmc(card)) {
2408+
if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
2409+
&mmc_dbg_ext_csd_fops))
2410+
return -EIO;
2411+
}
2412+
2413+
return 0;
2414+
}
2415+
2416+
2417+
#else
2418+
2419+
static int mmc_blk_add_debugfs(struct mmc_card *card)
2420+
{
2421+
return 0;
2422+
}
2423+
2424+
#endif /* CONFIG_DEBUG_FS */
2425+
22862426
static int mmc_blk_probe(struct mmc_card *card)
22872427
{
22882428
struct mmc_blk_data *md, *part_md;
@@ -2319,6 +2459,9 @@ static int mmc_blk_probe(struct mmc_card *card)
23192459
goto out;
23202460
}
23212461

2462+
/* Add two debugfs entries */
2463+
mmc_blk_add_debugfs(card);
2464+
23222465
pm_runtime_set_autosuspend_delay(&card->dev, 3000);
23232466
pm_runtime_use_autosuspend(&card->dev);
23242467

drivers/mmc/core/debugfs.c

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -281,85 +281,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host)
281281
debugfs_remove_recursive(host->debugfs_root);
282282
}
283283

284-
static int mmc_dbg_card_status_get(void *data, u64 *val)
285-
{
286-
struct mmc_card *card = data;
287-
u32 status;
288-
int ret;
289-
290-
mmc_get_card(card);
291-
292-
ret = mmc_send_status(data, &status);
293-
if (!ret)
294-
*val = status;
295-
296-
mmc_put_card(card);
297-
298-
return ret;
299-
}
300-
DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
301-
NULL, "%08llx\n");
302-
303-
#define EXT_CSD_STR_LEN 1025
304-
305-
static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
306-
{
307-
struct mmc_card *card = inode->i_private;
308-
char *buf;
309-
ssize_t n = 0;
310-
u8 *ext_csd;
311-
int err, i;
312-
313-
buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
314-
if (!buf)
315-
return -ENOMEM;
316-
317-
mmc_get_card(card);
318-
err = mmc_get_ext_csd(card, &ext_csd);
319-
mmc_put_card(card);
320-
if (err)
321-
goto out_free;
322-
323-
for (i = 0; i < 512; i++)
324-
n += sprintf(buf + n, "%02x", ext_csd[i]);
325-
n += sprintf(buf + n, "\n");
326-
327-
if (n != EXT_CSD_STR_LEN) {
328-
err = -EINVAL;
329-
goto out_free;
330-
}
331-
332-
filp->private_data = buf;
333-
kfree(ext_csd);
334-
return 0;
335-
336-
out_free:
337-
kfree(buf);
338-
return err;
339-
}
340-
341-
static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
342-
size_t cnt, loff_t *ppos)
343-
{
344-
char *buf = filp->private_data;
345-
346-
return simple_read_from_buffer(ubuf, cnt, ppos,
347-
buf, EXT_CSD_STR_LEN);
348-
}
349-
350-
static int mmc_ext_csd_release(struct inode *inode, struct file *file)
351-
{
352-
kfree(file->private_data);
353-
return 0;
354-
}
355-
356-
static const struct file_operations mmc_dbg_ext_csd_fops = {
357-
.open = mmc_ext_csd_open,
358-
.read = mmc_ext_csd_read,
359-
.release = mmc_ext_csd_release,
360-
.llseek = default_llseek,
361-
};
362-
363284
void mmc_add_card_debugfs(struct mmc_card *card)
364285
{
365286
struct mmc_host *host = card->host;
@@ -382,16 +303,6 @@ void mmc_add_card_debugfs(struct mmc_card *card)
382303
if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
383304
goto err;
384305

385-
if (mmc_card_mmc(card) || mmc_card_sd(card))
386-
if (!debugfs_create_file("status", S_IRUSR, root, card,
387-
&mmc_dbg_card_status_fops))
388-
goto err;
389-
390-
if (mmc_card_mmc(card))
391-
if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
392-
&mmc_dbg_ext_csd_fops))
393-
goto err;
394-
395306
return;
396307

397308
err:

drivers/mmc/core/queue.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ struct mmc_blk_request {
3636
* enum mmc_drv_op - enumerates the operations in the mmc_queue_req
3737
* @MMC_DRV_OP_IOCTL: ioctl operation
3838
* @MMC_DRV_OP_BOOT_WP: write protect boot partitions
39+
* @MMC_DRV_OP_GET_CARD_STATUS: get card status
40+
* @MMC_DRV_OP_GET_EXT_CSD: get the EXT CSD from an eMMC card
3941
*/
4042
enum mmc_drv_op {
4143
MMC_DRV_OP_IOCTL,
4244
MMC_DRV_OP_BOOT_WP,
45+
MMC_DRV_OP_GET_CARD_STATUS,
46+
MMC_DRV_OP_GET_EXT_CSD,
4347
};
4448

4549
struct mmc_queue_req {

0 commit comments

Comments
 (0)