.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2007-2008 Pierre Ossman |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License as published by |
---|
6 | | - * the Free Software Foundation; either version 2 of the License, or (at |
---|
7 | | - * your option) any later version. |
---|
8 | 4 | */ |
---|
9 | 5 | |
---|
10 | 6 | #include <linux/mmc/core.h> |
---|
.. | .. |
---|
75 | 71 | * @sg_len: length of currently mapped scatterlist @sg |
---|
76 | 72 | * @mem: allocated memory |
---|
77 | 73 | * @sg: scatterlist |
---|
| 74 | + * @sg_areq: scatterlist for non-blocking request |
---|
78 | 75 | */ |
---|
79 | 76 | struct mmc_test_area { |
---|
80 | 77 | unsigned long max_sz; |
---|
.. | .. |
---|
86 | 83 | unsigned int sg_len; |
---|
87 | 84 | struct mmc_test_mem *mem; |
---|
88 | 85 | struct scatterlist *sg; |
---|
| 86 | + struct scatterlist *sg_areq; |
---|
89 | 87 | }; |
---|
90 | 88 | |
---|
91 | 89 | /** |
---|
.. | .. |
---|
840 | 838 | } |
---|
841 | 839 | |
---|
842 | 840 | static int mmc_test_nonblock_transfer(struct mmc_test_card *test, |
---|
843 | | - struct scatterlist *sg, unsigned sg_len, |
---|
844 | | - unsigned dev_addr, unsigned blocks, |
---|
845 | | - unsigned blksz, int write, int count) |
---|
| 841 | + unsigned int dev_addr, int write, |
---|
| 842 | + int count) |
---|
846 | 843 | { |
---|
847 | 844 | struct mmc_test_req *rq1, *rq2; |
---|
848 | 845 | struct mmc_request *mrq, *prev_mrq; |
---|
849 | 846 | int i; |
---|
850 | 847 | int ret = RESULT_OK; |
---|
| 848 | + struct mmc_test_area *t = &test->area; |
---|
| 849 | + struct scatterlist *sg = t->sg; |
---|
| 850 | + struct scatterlist *sg_areq = t->sg_areq; |
---|
851 | 851 | |
---|
852 | 852 | rq1 = mmc_test_req_alloc(); |
---|
853 | 853 | rq2 = mmc_test_req_alloc(); |
---|
.. | .. |
---|
861 | 861 | |
---|
862 | 862 | for (i = 0; i < count; i++) { |
---|
863 | 863 | mmc_test_req_reset(container_of(mrq, struct mmc_test_req, mrq)); |
---|
864 | | - mmc_test_prepare_mrq(test, mrq, sg, sg_len, dev_addr, blocks, |
---|
865 | | - blksz, write); |
---|
| 864 | + mmc_test_prepare_mrq(test, mrq, sg, t->sg_len, dev_addr, |
---|
| 865 | + t->blocks, 512, write); |
---|
866 | 866 | ret = mmc_test_start_areq(test, mrq, prev_mrq); |
---|
867 | 867 | if (ret) |
---|
868 | 868 | goto err; |
---|
.. | .. |
---|
871 | 871 | prev_mrq = &rq2->mrq; |
---|
872 | 872 | |
---|
873 | 873 | swap(mrq, prev_mrq); |
---|
874 | | - dev_addr += blocks; |
---|
| 874 | + swap(sg, sg_areq); |
---|
| 875 | + dev_addr += t->blocks; |
---|
875 | 876 | } |
---|
876 | 877 | |
---|
877 | 878 | ret = mmc_test_start_areq(test, NULL, prev_mrq); |
---|
.. | .. |
---|
1400 | 1401 | * Map sz bytes so that it can be transferred. |
---|
1401 | 1402 | */ |
---|
1402 | 1403 | static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, |
---|
1403 | | - int max_scatter, int min_sg_len) |
---|
| 1404 | + int max_scatter, int min_sg_len, bool nonblock) |
---|
1404 | 1405 | { |
---|
1405 | 1406 | struct mmc_test_area *t = &test->area; |
---|
1406 | 1407 | int err; |
---|
| 1408 | + unsigned int sg_len = 0; |
---|
1407 | 1409 | |
---|
1408 | 1410 | t->blocks = sz >> 9; |
---|
1409 | 1411 | |
---|
.. | .. |
---|
1415 | 1417 | err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs, |
---|
1416 | 1418 | t->max_seg_sz, &t->sg_len, min_sg_len); |
---|
1417 | 1419 | } |
---|
| 1420 | + |
---|
| 1421 | + if (err || !nonblock) |
---|
| 1422 | + goto err; |
---|
| 1423 | + |
---|
| 1424 | + if (max_scatter) { |
---|
| 1425 | + err = mmc_test_map_sg_max_scatter(t->mem, sz, t->sg_areq, |
---|
| 1426 | + t->max_segs, t->max_seg_sz, |
---|
| 1427 | + &sg_len); |
---|
| 1428 | + } else { |
---|
| 1429 | + err = mmc_test_map_sg(t->mem, sz, t->sg_areq, 1, t->max_segs, |
---|
| 1430 | + t->max_seg_sz, &sg_len, min_sg_len); |
---|
| 1431 | + } |
---|
| 1432 | + if (!err && sg_len != t->sg_len) |
---|
| 1433 | + err = -EINVAL; |
---|
| 1434 | + |
---|
| 1435 | +err: |
---|
1418 | 1436 | if (err) |
---|
1419 | 1437 | pr_info("%s: Failed to map sg list\n", |
---|
1420 | 1438 | mmc_hostname(test->card->host)); |
---|
.. | .. |
---|
1444 | 1462 | struct timespec64 ts1, ts2; |
---|
1445 | 1463 | int ret = 0; |
---|
1446 | 1464 | int i; |
---|
1447 | | - struct mmc_test_area *t = &test->area; |
---|
1448 | 1465 | |
---|
1449 | 1466 | /* |
---|
1450 | 1467 | * In the case of a maximally scattered transfer, the maximum transfer |
---|
.. | .. |
---|
1462 | 1479 | sz = max_tfr; |
---|
1463 | 1480 | } |
---|
1464 | 1481 | |
---|
1465 | | - ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len); |
---|
| 1482 | + ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len, nonblock); |
---|
1466 | 1483 | if (ret) |
---|
1467 | 1484 | return ret; |
---|
1468 | 1485 | |
---|
1469 | 1486 | if (timed) |
---|
1470 | 1487 | ktime_get_ts64(&ts1); |
---|
1471 | 1488 | if (nonblock) |
---|
1472 | | - ret = mmc_test_nonblock_transfer(test, t->sg, t->sg_len, |
---|
1473 | | - dev_addr, t->blocks, 512, write, count); |
---|
| 1489 | + ret = mmc_test_nonblock_transfer(test, dev_addr, write, count); |
---|
1474 | 1490 | else |
---|
1475 | 1491 | for (i = 0; i < count && ret == 0; i++) { |
---|
1476 | 1492 | ret = mmc_test_area_transfer(test, dev_addr, write); |
---|
.. | .. |
---|
1529 | 1545 | struct mmc_test_area *t = &test->area; |
---|
1530 | 1546 | |
---|
1531 | 1547 | kfree(t->sg); |
---|
| 1548 | + kfree(t->sg_areq); |
---|
1532 | 1549 | mmc_test_free_mem(t->mem); |
---|
1533 | 1550 | |
---|
1534 | 1551 | return 0; |
---|
.. | .. |
---|
1584 | 1601 | |
---|
1585 | 1602 | t->sg = kmalloc_array(t->max_segs, sizeof(*t->sg), GFP_KERNEL); |
---|
1586 | 1603 | if (!t->sg) { |
---|
| 1604 | + ret = -ENOMEM; |
---|
| 1605 | + goto out_free; |
---|
| 1606 | + } |
---|
| 1607 | + |
---|
| 1608 | + t->sg_areq = kmalloc_array(t->max_segs, sizeof(*t->sg_areq), |
---|
| 1609 | + GFP_KERNEL); |
---|
| 1610 | + if (!t->sg_areq) { |
---|
1587 | 1611 | ret = -ENOMEM; |
---|
1588 | 1612 | goto out_free; |
---|
1589 | 1613 | } |
---|
.. | .. |
---|
2472 | 2496 | if (!(test->card->host->caps & MMC_CAP_CMD_DURING_TFR)) |
---|
2473 | 2497 | return RESULT_UNSUP_HOST; |
---|
2474 | 2498 | |
---|
2475 | | - ret = mmc_test_area_map(test, sz, 0, 0); |
---|
| 2499 | + ret = mmc_test_area_map(test, sz, 0, 0, use_areq); |
---|
2476 | 2500 | if (ret) |
---|
2477 | 2501 | return ret; |
---|
2478 | 2502 | |
---|
.. | .. |
---|
2645 | 2669 | }, |
---|
2646 | 2670 | |
---|
2647 | 2671 | { |
---|
2648 | | - .name = "Correct xfer_size at write (start failure)", |
---|
| 2672 | + .name = "Proper xfer_size at write (start failure)", |
---|
2649 | 2673 | .run = mmc_test_xfersize_write, |
---|
2650 | 2674 | }, |
---|
2651 | 2675 | |
---|
2652 | 2676 | { |
---|
2653 | | - .name = "Correct xfer_size at read (start failure)", |
---|
| 2677 | + .name = "Proper xfer_size at read (start failure)", |
---|
2654 | 2678 | .run = mmc_test_xfersize_read, |
---|
2655 | 2679 | }, |
---|
2656 | 2680 | |
---|
2657 | 2681 | { |
---|
2658 | | - .name = "Correct xfer_size at write (midway failure)", |
---|
| 2682 | + .name = "Proper xfer_size at write (midway failure)", |
---|
2659 | 2683 | .run = mmc_test_multi_xfersize_write, |
---|
2660 | 2684 | }, |
---|
2661 | 2685 | |
---|
2662 | 2686 | { |
---|
2663 | | - .name = "Correct xfer_size at read (midway failure)", |
---|
| 2687 | + .name = "Proper xfer_size at read (midway failure)", |
---|
2664 | 2688 | .run = mmc_test_multi_xfersize_read, |
---|
2665 | 2689 | }, |
---|
2666 | 2690 | |
---|
.. | .. |
---|
3145 | 3169 | return 0; |
---|
3146 | 3170 | } |
---|
3147 | 3171 | |
---|
3148 | | -static int mtf_testlist_open(struct inode *inode, struct file *file) |
---|
3149 | | -{ |
---|
3150 | | - return single_open(file, mtf_testlist_show, inode->i_private); |
---|
3151 | | -} |
---|
3152 | | - |
---|
3153 | | -static const struct file_operations mmc_test_fops_testlist = { |
---|
3154 | | - .open = mtf_testlist_open, |
---|
3155 | | - .read = seq_read, |
---|
3156 | | - .llseek = seq_lseek, |
---|
3157 | | - .release = single_release, |
---|
3158 | | -}; |
---|
| 3172 | +DEFINE_SHOW_ATTRIBUTE(mtf_testlist); |
---|
3159 | 3173 | |
---|
3160 | 3174 | static void mmc_test_free_dbgfs_file(struct mmc_card *card) |
---|
3161 | 3175 | { |
---|
.. | .. |
---|
3182 | 3196 | |
---|
3183 | 3197 | if (card->debugfs_root) |
---|
3184 | 3198 | file = debugfs_create_file(name, mode, card->debugfs_root, |
---|
3185 | | - card, fops); |
---|
3186 | | - |
---|
3187 | | - if (IS_ERR_OR_NULL(file)) { |
---|
3188 | | - dev_err(&card->dev, |
---|
3189 | | - "Can't create %s. Perhaps debugfs is disabled.\n", |
---|
3190 | | - name); |
---|
3191 | | - return -ENODEV; |
---|
3192 | | - } |
---|
| 3199 | + card, fops); |
---|
3193 | 3200 | |
---|
3194 | 3201 | df = kmalloc(sizeof(*df), GFP_KERNEL); |
---|
3195 | 3202 | if (!df) { |
---|
.. | .. |
---|
3216 | 3223 | goto err; |
---|
3217 | 3224 | |
---|
3218 | 3225 | ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO, |
---|
3219 | | - &mmc_test_fops_testlist); |
---|
| 3226 | + &mtf_testlist_fops); |
---|
3220 | 3227 | if (ret) |
---|
3221 | 3228 | goto err; |
---|
3222 | 3229 | |
---|