aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2017-08-20 17:39:08 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2017-08-30 09:03:39 -0400
commit627c3ccfb46ada2583eac434127ad5d75e1ac33c (patch)
tree0b47d6c685823ff30e76fc50a4f8cf43b5125307
parent1bee324a5627ab05ff9899709a613b8739813eda (diff)
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 <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/core/block.c143
-rw-r--r--drivers/mmc/core/debugfs.c89
-rw-r--r--drivers/mmc/core/queue.h4
3 files changed, 147 insertions, 89 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 727699c75ca4..274c1ed2646e 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -36,6 +36,7 @@
36#include <linux/compat.h> 36#include <linux/compat.h>
37#include <linux/pm_runtime.h> 37#include <linux/pm_runtime.h>
38#include <linux/idr.h> 38#include <linux/idr.h>
39#include <linux/debugfs.h>
39 40
40#include <linux/mmc/ioctl.h> 41#include <linux/mmc/ioctl.h>
41#include <linux/mmc/card.h> 42#include <linux/mmc/card.h>
@@ -1177,6 +1178,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
1177 struct mmc_card *card = mq->card; 1178 struct mmc_card *card = mq->card;
1178 struct mmc_blk_data *md = mq->blkdata; 1179 struct mmc_blk_data *md = mq->blkdata;
1179 struct mmc_blk_ioc_data **idata; 1180 struct mmc_blk_ioc_data **idata;
1181 u8 **ext_csd;
1182 u32 status;
1180 int ret; 1183 int ret;
1181 int i; 1184 int i;
1182 1185
@@ -1206,6 +1209,15 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
1206 card->ext_csd.boot_ro_lock |= 1209 card->ext_csd.boot_ro_lock |=
1207 EXT_CSD_BOOT_WP_B_PWR_WP_EN; 1210 EXT_CSD_BOOT_WP_B_PWR_WP_EN;
1208 break; 1211 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;
1209 default: 1221 default:
1210 pr_err("%s: unknown driver specific operation\n", 1222 pr_err("%s: unknown driver specific operation\n",
1211 md->disk->disk_name); 1223 md->disk->disk_name);
@@ -2283,6 +2295,134 @@ force_ro_fail:
2283 return ret; 2295 return ret;
2284} 2296}
2285 2297
2298#ifdef CONFIG_DEBUG_FS
2299
2300static 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}
2320DEFINE_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
2326static 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
2365out_free:
2366 kfree(buf);
2367 return err;
2368}
2369
2370static 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
2379static int mmc_ext_csd_release(struct inode *inode, struct file *file)
2380{
2381 kfree(file->private_data);
2382 return 0;
2383}
2384
2385static 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
2392static 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
2419static int mmc_blk_add_debugfs(struct mmc_card *card)
2420{
2421 return 0;
2422}
2423
2424#endif /* CONFIG_DEBUG_FS */
2425
2286static int mmc_blk_probe(struct mmc_card *card) 2426static int mmc_blk_probe(struct mmc_card *card)
2287{ 2427{
2288 struct mmc_blk_data *md, *part_md; 2428 struct mmc_blk_data *md, *part_md;
@@ -2319,6 +2459,9 @@ static int mmc_blk_probe(struct mmc_card *card)
2319 goto out; 2459 goto out;
2320 } 2460 }
2321 2461
2462 /* Add two debugfs entries */
2463 mmc_blk_add_debugfs(card);
2464
2322 pm_runtime_set_autosuspend_delay(&card->dev, 3000); 2465 pm_runtime_set_autosuspend_delay(&card->dev, 3000);
2323 pm_runtime_use_autosuspend(&card->dev); 2466 pm_runtime_use_autosuspend(&card->dev);
2324 2467
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index a1fba5732d66..01e459a34f33 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -281,85 +281,6 @@ void mmc_remove_host_debugfs(struct mmc_host *host)
281 debugfs_remove_recursive(host->debugfs_root); 281 debugfs_remove_recursive(host->debugfs_root);
282} 282}
283 283
284static 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}
300DEFINE_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
305static 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
336out_free:
337 kfree(buf);
338 return err;
339}
340
341static 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
350static int mmc_ext_csd_release(struct inode *inode, struct file *file)
351{
352 kfree(file->private_data);
353 return 0;
354}
355
356static 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
363void mmc_add_card_debugfs(struct mmc_card *card) 284void mmc_add_card_debugfs(struct mmc_card *card)
364{ 285{
365 struct mmc_host *host = card->host; 286 struct mmc_host *host = card->host;
@@ -382,16 +303,6 @@ void mmc_add_card_debugfs(struct mmc_card *card)
382 if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) 303 if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
383 goto err; 304 goto err;
384 305
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
395 return; 306 return;
396 307
397err: 308err:
diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h
index cf26a15a64bf..04fc89360a7a 100644
--- a/drivers/mmc/core/queue.h
+++ b/drivers/mmc/core/queue.h
@@ -36,10 +36,14 @@ struct mmc_blk_request {
36 * enum mmc_drv_op - enumerates the operations in the mmc_queue_req 36 * enum mmc_drv_op - enumerates the operations in the mmc_queue_req
37 * @MMC_DRV_OP_IOCTL: ioctl operation 37 * @MMC_DRV_OP_IOCTL: ioctl operation
38 * @MMC_DRV_OP_BOOT_WP: write protect boot partitions 38 * @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
39 */ 41 */
40enum mmc_drv_op { 42enum mmc_drv_op {
41 MMC_DRV_OP_IOCTL, 43 MMC_DRV_OP_IOCTL,
42 MMC_DRV_OP_BOOT_WP, 44 MMC_DRV_OP_BOOT_WP,
45 MMC_DRV_OP_GET_CARD_STATUS,
46 MMC_DRV_OP_GET_EXT_CSD,
43}; 47};
44 48
45struct mmc_queue_req { 49struct mmc_queue_req {