mmc_test.c revision b7ac2cf1cdf346b34cbc2104d386a9d29d12aa4c
1/* 2 * linux/drivers/mmc/card/mmc_test.c 3 * 4 * Copyright 2007-2008 Pierre Ossman 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or (at 9 * your option) any later version. 10 */ 11 12#include <linux/mmc/core.h> 13#include <linux/mmc/card.h> 14#include <linux/mmc/host.h> 15#include <linux/mmc/mmc.h> 16 17#include <linux/scatterlist.h> 18 19#define RESULT_OK 0 20#define RESULT_FAIL 1 21#define RESULT_UNSUP_HOST 2 22#define RESULT_UNSUP_CARD 3 23 24#define BUFFER_ORDER 2 25#define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) 26 27struct mmc_test_card { 28 struct mmc_card *card; 29 30 u8 scratch[BUFFER_SIZE]; 31 u8 *buffer; 32#ifdef CONFIG_HIGHMEM 33 struct page *highmem; 34#endif 35}; 36 37/*******************************************************************/ 38/* General helper functions */ 39/*******************************************************************/ 40 41/* 42 * Configure correct block size in card 43 */ 44static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) 45{ 46 struct mmc_command cmd; 47 int ret; 48 49 cmd.opcode = MMC_SET_BLOCKLEN; 50 cmd.arg = size; 51 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 52 ret = mmc_wait_for_cmd(test->card->host, &cmd, 0); 53 if (ret) 54 return ret; 55 56 return 0; 57} 58 59/* 60 * Fill in the mmc_request structure given a set of transfer parameters. 61 */ 62static void mmc_test_prepare_mrq(struct mmc_test_card *test, 63 struct mmc_request *mrq, struct scatterlist *sg, unsigned sg_len, 64 unsigned dev_addr, unsigned blocks, unsigned blksz, int write) 65{ 66 BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop); 67 68 if (blocks > 1) { 69 mrq->cmd->opcode = write ? 70 MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK; 71 } else { 72 mrq->cmd->opcode = write ? 73 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; 74 } 75 76 mrq->cmd->arg = dev_addr; 77 mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; 78 79 if (blocks == 1) 80 mrq->stop = NULL; 81 else { 82 mrq->stop->opcode = MMC_STOP_TRANSMISSION; 83 mrq->stop->arg = 0; 84 mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC; 85 } 86 87 mrq->data->blksz = blksz; 88 mrq->data->blocks = blocks; 89 mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; 90 mrq->data->sg = sg; 91 mrq->data->sg_len = sg_len; 92 93 mmc_set_data_timeout(mrq->data, test->card); 94} 95 96/* 97 * Wait for the card to finish the busy state 98 */ 99static int mmc_test_wait_busy(struct mmc_test_card *test) 100{ 101 int ret, busy; 102 struct mmc_command cmd; 103 104 busy = 0; 105 do { 106 memset(&cmd, 0, sizeof(struct mmc_command)); 107 108 cmd.opcode = MMC_SEND_STATUS; 109 cmd.arg = test->card->rca << 16; 110 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; 111 112 ret = mmc_wait_for_cmd(test->card->host, &cmd, 0); 113 if (ret) 114 break; 115 116 if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) { 117 busy = 1; 118 printk(KERN_INFO "%s: Warning: Host did not " 119 "wait for busy state to end.\n", 120 mmc_hostname(test->card->host)); 121 } 122 } while (!(cmd.resp[0] & R1_READY_FOR_DATA)); 123 124 return ret; 125} 126 127/* 128 * Transfer a single sector of kernel addressable data 129 */ 130static int mmc_test_buffer_transfer(struct mmc_test_card *test, 131 u8 *buffer, unsigned addr, unsigned blksz, int write) 132{ 133 int ret; 134 135 struct mmc_request mrq; 136 struct mmc_command cmd; 137 struct mmc_command stop; 138 struct mmc_data data; 139 140 struct scatterlist sg; 141 142 memset(&mrq, 0, sizeof(struct mmc_request)); 143 memset(&cmd, 0, sizeof(struct mmc_command)); 144 memset(&data, 0, sizeof(struct mmc_data)); 145 memset(&stop, 0, sizeof(struct mmc_command)); 146 147 mrq.cmd = &cmd; 148 mrq.data = &data; 149 mrq.stop = &stop; 150 151 sg_init_one(&sg, buffer, blksz); 152 153 mmc_test_prepare_mrq(test, &mrq, &sg, 1, addr, 1, blksz, write); 154 155 mmc_wait_for_req(test->card->host, &mrq); 156 157 if (cmd.error) 158 return cmd.error; 159 if (data.error) 160 return data.error; 161 162 ret = mmc_test_wait_busy(test); 163 if (ret) 164 return ret; 165 166 return 0; 167} 168 169/*******************************************************************/ 170/* Test preparation and cleanup */ 171/*******************************************************************/ 172 173/* 174 * Fill the first couple of sectors of the card with known data 175 * so that bad reads/writes can be detected 176 */ 177static int __mmc_test_prepare(struct mmc_test_card *test, int write) 178{ 179 int ret, i; 180 181 ret = mmc_test_set_blksize(test, 512); 182 if (ret) 183 return ret; 184 185 if (write) 186 memset(test->buffer, 0xDF, 512); 187 else { 188 for (i = 0;i < 512;i++) 189 test->buffer[i] = i; 190 } 191 192 for (i = 0;i < BUFFER_SIZE / 512;i++) { 193 ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); 194 if (ret) 195 return ret; 196 } 197 198 return 0; 199} 200 201static int mmc_test_prepare_write(struct mmc_test_card *test) 202{ 203 return __mmc_test_prepare(test, 1); 204} 205 206static int mmc_test_prepare_read(struct mmc_test_card *test) 207{ 208 return __mmc_test_prepare(test, 0); 209} 210 211static int mmc_test_cleanup(struct mmc_test_card *test) 212{ 213 int ret, i; 214 215 ret = mmc_test_set_blksize(test, 512); 216 if (ret) 217 return ret; 218 219 memset(test->buffer, 0, 512); 220 221 for (i = 0;i < BUFFER_SIZE / 512;i++) { 222 ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); 223 if (ret) 224 return ret; 225 } 226 227 return 0; 228} 229 230/*******************************************************************/ 231/* Test execution helpers */ 232/*******************************************************************/ 233 234/* 235 * Modifies the mmc_request to perform the "short transfer" tests 236 */ 237static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test, 238 struct mmc_request *mrq, int write) 239{ 240 BUG_ON(!mrq || !mrq->cmd || !mrq->data); 241 242 if (mrq->data->blocks > 1) { 243 mrq->cmd->opcode = write ? 244 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; 245 mrq->stop = NULL; 246 } else { 247 mrq->cmd->opcode = MMC_SEND_STATUS; 248 mrq->cmd->arg = test->card->rca << 16; 249 } 250} 251 252/* 253 * Checks that a normal transfer didn't have any errors 254 */ 255static int mmc_test_check_result(struct mmc_test_card *test, 256 struct mmc_request *mrq) 257{ 258 int ret; 259 260 BUG_ON(!mrq || !mrq->cmd || !mrq->data); 261 262 ret = 0; 263 264 if (!ret && mrq->cmd->error) 265 ret = mrq->cmd->error; 266 if (!ret && mrq->data->error) 267 ret = mrq->data->error; 268 if (!ret && mrq->stop && mrq->stop->error) 269 ret = mrq->stop->error; 270 if (!ret && mrq->data->bytes_xfered != 271 mrq->data->blocks * mrq->data->blksz) 272 ret = RESULT_FAIL; 273 274 if (ret == -EINVAL) 275 ret = RESULT_UNSUP_HOST; 276 277 return ret; 278} 279 280/* 281 * Checks that a "short transfer" behaved as expected 282 */ 283static int mmc_test_check_broken_result(struct mmc_test_card *test, 284 struct mmc_request *mrq) 285{ 286 int ret; 287 288 BUG_ON(!mrq || !mrq->cmd || !mrq->data); 289 290 ret = 0; 291 292 if (!ret && mrq->cmd->error) 293 ret = mrq->cmd->error; 294 if (!ret && mrq->data->error == 0) 295 ret = RESULT_FAIL; 296 if (!ret && mrq->data->error != -ETIMEDOUT) 297 ret = mrq->data->error; 298 if (!ret && mrq->stop && mrq->stop->error) 299 ret = mrq->stop->error; 300 if (mrq->data->blocks > 1) { 301 if (!ret && mrq->data->bytes_xfered > mrq->data->blksz) 302 ret = RESULT_FAIL; 303 } else { 304 if (!ret && mrq->data->bytes_xfered > 0) 305 ret = RESULT_FAIL; 306 } 307 308 if (ret == -EINVAL) 309 ret = RESULT_UNSUP_HOST; 310 311 return ret; 312} 313 314/* 315 * Tests a basic transfer with certain parameters 316 */ 317static int mmc_test_simple_transfer(struct mmc_test_card *test, 318 struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, 319 unsigned blocks, unsigned blksz, int write) 320{ 321 struct mmc_request mrq; 322 struct mmc_command cmd; 323 struct mmc_command stop; 324 struct mmc_data data; 325 326 memset(&mrq, 0, sizeof(struct mmc_request)); 327 memset(&cmd, 0, sizeof(struct mmc_command)); 328 memset(&data, 0, sizeof(struct mmc_data)); 329 memset(&stop, 0, sizeof(struct mmc_command)); 330 331 mrq.cmd = &cmd; 332 mrq.data = &data; 333 mrq.stop = &stop; 334 335 mmc_test_prepare_mrq(test, &mrq, sg, sg_len, dev_addr, 336 blocks, blksz, write); 337 338 mmc_wait_for_req(test->card->host, &mrq); 339 340 mmc_test_wait_busy(test); 341 342 return mmc_test_check_result(test, &mrq); 343} 344 345/* 346 * Tests a transfer where the card will fail completely or partly 347 */ 348static int mmc_test_broken_transfer(struct mmc_test_card *test, 349 unsigned blocks, unsigned blksz, int write) 350{ 351 struct mmc_request mrq; 352 struct mmc_command cmd; 353 struct mmc_command stop; 354 struct mmc_data data; 355 356 struct scatterlist sg; 357 358 memset(&mrq, 0, sizeof(struct mmc_request)); 359 memset(&cmd, 0, sizeof(struct mmc_command)); 360 memset(&data, 0, sizeof(struct mmc_data)); 361 memset(&stop, 0, sizeof(struct mmc_command)); 362 363 mrq.cmd = &cmd; 364 mrq.data = &data; 365 mrq.stop = &stop; 366 367 sg_init_one(&sg, test->buffer, blocks * blksz); 368 369 mmc_test_prepare_mrq(test, &mrq, &sg, 1, 0, blocks, blksz, write); 370 mmc_test_prepare_broken_mrq(test, &mrq, write); 371 372 mmc_wait_for_req(test->card->host, &mrq); 373 374 mmc_test_wait_busy(test); 375 376 return mmc_test_check_broken_result(test, &mrq); 377} 378 379/* 380 * Does a complete transfer test where data is also validated 381 * 382 * Note: mmc_test_prepare() must have been done before this call 383 */ 384static int mmc_test_transfer(struct mmc_test_card *test, 385 struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, 386 unsigned blocks, unsigned blksz, int write) 387{ 388 int ret, i; 389 unsigned long flags; 390 391 if (write) { 392 for (i = 0;i < blocks * blksz;i++) 393 test->scratch[i] = i; 394 } else { 395 memset(test->scratch, 0, BUFFER_SIZE); 396 } 397 local_irq_save(flags); 398 sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); 399 local_irq_restore(flags); 400 401 ret = mmc_test_set_blksize(test, blksz); 402 if (ret) 403 return ret; 404 405 ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr, 406 blocks, blksz, write); 407 if (ret) 408 return ret; 409 410 if (write) { 411 int sectors; 412 413 ret = mmc_test_set_blksize(test, 512); 414 if (ret) 415 return ret; 416 417 sectors = (blocks * blksz + 511) / 512; 418 if ((sectors * 512) == (blocks * blksz)) 419 sectors++; 420 421 if ((sectors * 512) > BUFFER_SIZE) 422 return -EINVAL; 423 424 memset(test->buffer, 0, sectors * 512); 425 426 for (i = 0;i < sectors;i++) { 427 ret = mmc_test_buffer_transfer(test, 428 test->buffer + i * 512, 429 dev_addr + i * 512, 512, 0); 430 if (ret) 431 return ret; 432 } 433 434 for (i = 0;i < blocks * blksz;i++) { 435 if (test->buffer[i] != (u8)i) 436 return RESULT_FAIL; 437 } 438 439 for (;i < sectors * 512;i++) { 440 if (test->buffer[i] != 0xDF) 441 return RESULT_FAIL; 442 } 443 } else { 444 local_irq_save(flags); 445 sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); 446 local_irq_restore(flags); 447 for (i = 0;i < blocks * blksz;i++) { 448 if (test->scratch[i] != (u8)i) 449 return RESULT_FAIL; 450 } 451 } 452 453 return 0; 454} 455 456/*******************************************************************/ 457/* Tests */ 458/*******************************************************************/ 459 460struct mmc_test_case { 461 const char *name; 462 463 int (*prepare)(struct mmc_test_card *); 464 int (*run)(struct mmc_test_card *); 465 int (*cleanup)(struct mmc_test_card *); 466}; 467 468static int mmc_test_basic_write(struct mmc_test_card *test) 469{ 470 int ret; 471 struct scatterlist sg; 472 473 ret = mmc_test_set_blksize(test, 512); 474 if (ret) 475 return ret; 476 477 sg_init_one(&sg, test->buffer, 512); 478 479 ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1); 480 if (ret) 481 return ret; 482 483 return 0; 484} 485 486static int mmc_test_basic_read(struct mmc_test_card *test) 487{ 488 int ret; 489 struct scatterlist sg; 490 491 ret = mmc_test_set_blksize(test, 512); 492 if (ret) 493 return ret; 494 495 sg_init_one(&sg, test->buffer, 512); 496 497 ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1); 498 if (ret) 499 return ret; 500 501 return 0; 502} 503 504static int mmc_test_verify_write(struct mmc_test_card *test) 505{ 506 int ret; 507 struct scatterlist sg; 508 509 sg_init_one(&sg, test->buffer, 512); 510 511 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1); 512 if (ret) 513 return ret; 514 515 return 0; 516} 517 518static int mmc_test_verify_read(struct mmc_test_card *test) 519{ 520 int ret; 521 struct scatterlist sg; 522 523 sg_init_one(&sg, test->buffer, 512); 524 525 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0); 526 if (ret) 527 return ret; 528 529 return 0; 530} 531 532static int mmc_test_multi_write(struct mmc_test_card *test) 533{ 534 int ret; 535 unsigned int size; 536 struct scatterlist sg; 537 538 if (test->card->host->max_blk_count == 1) 539 return RESULT_UNSUP_HOST; 540 541 size = PAGE_SIZE * 2; 542 size = min(size, test->card->host->max_req_size); 543 size = min(size, test->card->host->max_seg_size); 544 size = min(size, test->card->host->max_blk_count * 512); 545 546 if (size < 1024) 547 return RESULT_UNSUP_HOST; 548 549 sg_init_one(&sg, test->buffer, size); 550 551 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); 552 if (ret) 553 return ret; 554 555 return 0; 556} 557 558static int mmc_test_multi_read(struct mmc_test_card *test) 559{ 560 int ret; 561 unsigned int size; 562 struct scatterlist sg; 563 564 if (test->card->host->max_blk_count == 1) 565 return RESULT_UNSUP_HOST; 566 567 size = PAGE_SIZE * 2; 568 size = min(size, test->card->host->max_req_size); 569 size = min(size, test->card->host->max_seg_size); 570 size = min(size, test->card->host->max_blk_count * 512); 571 572 if (size < 1024) 573 return RESULT_UNSUP_HOST; 574 575 sg_init_one(&sg, test->buffer, size); 576 577 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); 578 if (ret) 579 return ret; 580 581 return 0; 582} 583 584static int mmc_test_pow2_write(struct mmc_test_card *test) 585{ 586 int ret, i; 587 struct scatterlist sg; 588 589 if (!test->card->csd.write_partial) 590 return RESULT_UNSUP_CARD; 591 592 for (i = 1; i < 512;i <<= 1) { 593 sg_init_one(&sg, test->buffer, i); 594 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1); 595 if (ret) 596 return ret; 597 } 598 599 return 0; 600} 601 602static int mmc_test_pow2_read(struct mmc_test_card *test) 603{ 604 int ret, i; 605 struct scatterlist sg; 606 607 if (!test->card->csd.read_partial) 608 return RESULT_UNSUP_CARD; 609 610 for (i = 1; i < 512;i <<= 1) { 611 sg_init_one(&sg, test->buffer, i); 612 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0); 613 if (ret) 614 return ret; 615 } 616 617 return 0; 618} 619 620static int mmc_test_weird_write(struct mmc_test_card *test) 621{ 622 int ret, i; 623 struct scatterlist sg; 624 625 if (!test->card->csd.write_partial) 626 return RESULT_UNSUP_CARD; 627 628 for (i = 3; i < 512;i += 7) { 629 sg_init_one(&sg, test->buffer, i); 630 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1); 631 if (ret) 632 return ret; 633 } 634 635 return 0; 636} 637 638static int mmc_test_weird_read(struct mmc_test_card *test) 639{ 640 int ret, i; 641 struct scatterlist sg; 642 643 if (!test->card->csd.read_partial) 644 return RESULT_UNSUP_CARD; 645 646 for (i = 3; i < 512;i += 7) { 647 sg_init_one(&sg, test->buffer, i); 648 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0); 649 if (ret) 650 return ret; 651 } 652 653 return 0; 654} 655 656static int mmc_test_align_write(struct mmc_test_card *test) 657{ 658 int ret, i; 659 struct scatterlist sg; 660 661 for (i = 1;i < 4;i++) { 662 sg_init_one(&sg, test->buffer + i, 512); 663 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1); 664 if (ret) 665 return ret; 666 } 667 668 return 0; 669} 670 671static int mmc_test_align_read(struct mmc_test_card *test) 672{ 673 int ret, i; 674 struct scatterlist sg; 675 676 for (i = 1;i < 4;i++) { 677 sg_init_one(&sg, test->buffer + i, 512); 678 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0); 679 if (ret) 680 return ret; 681 } 682 683 return 0; 684} 685 686static int mmc_test_align_multi_write(struct mmc_test_card *test) 687{ 688 int ret, i; 689 unsigned int size; 690 struct scatterlist sg; 691 692 if (test->card->host->max_blk_count == 1) 693 return RESULT_UNSUP_HOST; 694 695 size = PAGE_SIZE * 2; 696 size = min(size, test->card->host->max_req_size); 697 size = min(size, test->card->host->max_seg_size); 698 size = min(size, test->card->host->max_blk_count * 512); 699 700 if (size < 1024) 701 return RESULT_UNSUP_HOST; 702 703 for (i = 1;i < 4;i++) { 704 sg_init_one(&sg, test->buffer + i, size); 705 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); 706 if (ret) 707 return ret; 708 } 709 710 return 0; 711} 712 713static int mmc_test_align_multi_read(struct mmc_test_card *test) 714{ 715 int ret, i; 716 unsigned int size; 717 struct scatterlist sg; 718 719 if (test->card->host->max_blk_count == 1) 720 return RESULT_UNSUP_HOST; 721 722 size = PAGE_SIZE * 2; 723 size = min(size, test->card->host->max_req_size); 724 size = min(size, test->card->host->max_seg_size); 725 size = min(size, test->card->host->max_blk_count * 512); 726 727 if (size < 1024) 728 return RESULT_UNSUP_HOST; 729 730 for (i = 1;i < 4;i++) { 731 sg_init_one(&sg, test->buffer + i, size); 732 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); 733 if (ret) 734 return ret; 735 } 736 737 return 0; 738} 739 740static int mmc_test_xfersize_write(struct mmc_test_card *test) 741{ 742 int ret; 743 744 ret = mmc_test_set_blksize(test, 512); 745 if (ret) 746 return ret; 747 748 ret = mmc_test_broken_transfer(test, 1, 512, 1); 749 if (ret) 750 return ret; 751 752 return 0; 753} 754 755static int mmc_test_xfersize_read(struct mmc_test_card *test) 756{ 757 int ret; 758 759 ret = mmc_test_set_blksize(test, 512); 760 if (ret) 761 return ret; 762 763 ret = mmc_test_broken_transfer(test, 1, 512, 0); 764 if (ret) 765 return ret; 766 767 return 0; 768} 769 770static int mmc_test_multi_xfersize_write(struct mmc_test_card *test) 771{ 772 int ret; 773 774 if (test->card->host->max_blk_count == 1) 775 return RESULT_UNSUP_HOST; 776 777 ret = mmc_test_set_blksize(test, 512); 778 if (ret) 779 return ret; 780 781 ret = mmc_test_broken_transfer(test, 2, 512, 1); 782 if (ret) 783 return ret; 784 785 return 0; 786} 787 788static int mmc_test_multi_xfersize_read(struct mmc_test_card *test) 789{ 790 int ret; 791 792 if (test->card->host->max_blk_count == 1) 793 return RESULT_UNSUP_HOST; 794 795 ret = mmc_test_set_blksize(test, 512); 796 if (ret) 797 return ret; 798 799 ret = mmc_test_broken_transfer(test, 2, 512, 0); 800 if (ret) 801 return ret; 802 803 return 0; 804} 805 806#ifdef CONFIG_HIGHMEM 807 808static int mmc_test_write_high(struct mmc_test_card *test) 809{ 810 int ret; 811 struct scatterlist sg; 812 813 sg_init_table(&sg, 1); 814 sg_set_page(&sg, test->highmem, 512, 0); 815 816 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1); 817 if (ret) 818 return ret; 819 820 return 0; 821} 822 823static int mmc_test_read_high(struct mmc_test_card *test) 824{ 825 int ret; 826 struct scatterlist sg; 827 828 sg_init_table(&sg, 1); 829 sg_set_page(&sg, test->highmem, 512, 0); 830 831 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0); 832 if (ret) 833 return ret; 834 835 return 0; 836} 837 838static int mmc_test_multi_write_high(struct mmc_test_card *test) 839{ 840 int ret; 841 unsigned int size; 842 struct scatterlist sg; 843 844 if (test->card->host->max_blk_count == 1) 845 return RESULT_UNSUP_HOST; 846 847 size = PAGE_SIZE * 2; 848 size = min(size, test->card->host->max_req_size); 849 size = min(size, test->card->host->max_seg_size); 850 size = min(size, test->card->host->max_blk_count * 512); 851 852 if (size < 1024) 853 return RESULT_UNSUP_HOST; 854 855 sg_init_table(&sg, 1); 856 sg_set_page(&sg, test->highmem, size, 0); 857 858 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); 859 if (ret) 860 return ret; 861 862 return 0; 863} 864 865static int mmc_test_multi_read_high(struct mmc_test_card *test) 866{ 867 int ret; 868 unsigned int size; 869 struct scatterlist sg; 870 871 if (test->card->host->max_blk_count == 1) 872 return RESULT_UNSUP_HOST; 873 874 size = PAGE_SIZE * 2; 875 size = min(size, test->card->host->max_req_size); 876 size = min(size, test->card->host->max_seg_size); 877 size = min(size, test->card->host->max_blk_count * 512); 878 879 if (size < 1024) 880 return RESULT_UNSUP_HOST; 881 882 sg_init_table(&sg, 1); 883 sg_set_page(&sg, test->highmem, size, 0); 884 885 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); 886 if (ret) 887 return ret; 888 889 return 0; 890} 891 892#endif /* CONFIG_HIGHMEM */ 893 894static const struct mmc_test_case mmc_test_cases[] = { 895 { 896 .name = "Basic write (no data verification)", 897 .run = mmc_test_basic_write, 898 }, 899 900 { 901 .name = "Basic read (no data verification)", 902 .run = mmc_test_basic_read, 903 }, 904 905 { 906 .name = "Basic write (with data verification)", 907 .prepare = mmc_test_prepare_write, 908 .run = mmc_test_verify_write, 909 .cleanup = mmc_test_cleanup, 910 }, 911 912 { 913 .name = "Basic read (with data verification)", 914 .prepare = mmc_test_prepare_read, 915 .run = mmc_test_verify_read, 916 .cleanup = mmc_test_cleanup, 917 }, 918 919 { 920 .name = "Multi-block write", 921 .prepare = mmc_test_prepare_write, 922 .run = mmc_test_multi_write, 923 .cleanup = mmc_test_cleanup, 924 }, 925 926 { 927 .name = "Multi-block read", 928 .prepare = mmc_test_prepare_read, 929 .run = mmc_test_multi_read, 930 .cleanup = mmc_test_cleanup, 931 }, 932 933 { 934 .name = "Power of two block writes", 935 .prepare = mmc_test_prepare_write, 936 .run = mmc_test_pow2_write, 937 .cleanup = mmc_test_cleanup, 938 }, 939 940 { 941 .name = "Power of two block reads", 942 .prepare = mmc_test_prepare_read, 943 .run = mmc_test_pow2_read, 944 .cleanup = mmc_test_cleanup, 945 }, 946 947 { 948 .name = "Weird sized block writes", 949 .prepare = mmc_test_prepare_write, 950 .run = mmc_test_weird_write, 951 .cleanup = mmc_test_cleanup, 952 }, 953 954 { 955 .name = "Weird sized block reads", 956 .prepare = mmc_test_prepare_read, 957 .run = mmc_test_weird_read, 958 .cleanup = mmc_test_cleanup, 959 }, 960 961 { 962 .name = "Badly aligned write", 963 .prepare = mmc_test_prepare_write, 964 .run = mmc_test_align_write, 965 .cleanup = mmc_test_cleanup, 966 }, 967 968 { 969 .name = "Badly aligned read", 970 .prepare = mmc_test_prepare_read, 971 .run = mmc_test_align_read, 972 .cleanup = mmc_test_cleanup, 973 }, 974 975 { 976 .name = "Badly aligned multi-block write", 977 .prepare = mmc_test_prepare_write, 978 .run = mmc_test_align_multi_write, 979 .cleanup = mmc_test_cleanup, 980 }, 981 982 { 983 .name = "Badly aligned multi-block read", 984 .prepare = mmc_test_prepare_read, 985 .run = mmc_test_align_multi_read, 986 .cleanup = mmc_test_cleanup, 987 }, 988 989 { 990 .name = "Correct xfer_size at write (start failure)", 991 .run = mmc_test_xfersize_write, 992 }, 993 994 { 995 .name = "Correct xfer_size at read (start failure)", 996 .run = mmc_test_xfersize_read, 997 }, 998 999 { 1000 .name = "Correct xfer_size at write (midway failure)", 1001 .run = mmc_test_multi_xfersize_write, 1002 }, 1003 1004 { 1005 .name = "Correct xfer_size at read (midway failure)", 1006 .run = mmc_test_multi_xfersize_read, 1007 }, 1008 1009#ifdef CONFIG_HIGHMEM 1010 1011 { 1012 .name = "Highmem write", 1013 .prepare = mmc_test_prepare_write, 1014 .run = mmc_test_write_high, 1015 .cleanup = mmc_test_cleanup, 1016 }, 1017 1018 { 1019 .name = "Highmem read", 1020 .prepare = mmc_test_prepare_read, 1021 .run = mmc_test_read_high, 1022 .cleanup = mmc_test_cleanup, 1023 }, 1024 1025 { 1026 .name = "Multi-block highmem write", 1027 .prepare = mmc_test_prepare_write, 1028 .run = mmc_test_multi_write_high, 1029 .cleanup = mmc_test_cleanup, 1030 }, 1031 1032 { 1033 .name = "Multi-block highmem read", 1034 .prepare = mmc_test_prepare_read, 1035 .run = mmc_test_multi_read_high, 1036 .cleanup = mmc_test_cleanup, 1037 }, 1038 1039#endif /* CONFIG_HIGHMEM */ 1040 1041}; 1042 1043static struct mutex mmc_test_lock; 1044 1045static void mmc_test_run(struct mmc_test_card *test, int testcase) 1046{ 1047 int i, ret; 1048 1049 printk(KERN_INFO "%s: Starting tests of card %s...\n", 1050 mmc_hostname(test->card->host), mmc_card_id(test->card)); 1051 1052 mmc_claim_host(test->card->host); 1053 1054 for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) { 1055 if (testcase && ((i + 1) != testcase)) 1056 continue; 1057 1058 printk(KERN_INFO "%s: Test case %d. %s...\n", 1059 mmc_hostname(test->card->host), i + 1, 1060 mmc_test_cases[i].name); 1061 1062 if (mmc_test_cases[i].prepare) { 1063 ret = mmc_test_cases[i].prepare(test); 1064 if (ret) { 1065 printk(KERN_INFO "%s: Result: Prepare " 1066 "stage failed! (%d)\n", 1067 mmc_hostname(test->card->host), 1068 ret); 1069 continue; 1070 } 1071 } 1072 1073 ret = mmc_test_cases[i].run(test); 1074 switch (ret) { 1075 case RESULT_OK: 1076 printk(KERN_INFO "%s: Result: OK\n", 1077 mmc_hostname(test->card->host)); 1078 break; 1079 case RESULT_FAIL: 1080 printk(KERN_INFO "%s: Result: FAILED\n", 1081 mmc_hostname(test->card->host)); 1082 break; 1083 case RESULT_UNSUP_HOST: 1084 printk(KERN_INFO "%s: Result: UNSUPPORTED " 1085 "(by host)\n", 1086 mmc_hostname(test->card->host)); 1087 break; 1088 case RESULT_UNSUP_CARD: 1089 printk(KERN_INFO "%s: Result: UNSUPPORTED " 1090 "(by card)\n", 1091 mmc_hostname(test->card->host)); 1092 break; 1093 default: 1094 printk(KERN_INFO "%s: Result: ERROR (%d)\n", 1095 mmc_hostname(test->card->host), ret); 1096 } 1097 1098 if (mmc_test_cases[i].cleanup) { 1099 ret = mmc_test_cases[i].cleanup(test); 1100 if (ret) { 1101 printk(KERN_INFO "%s: Warning: Cleanup " 1102 "stage failed! (%d)\n", 1103 mmc_hostname(test->card->host), 1104 ret); 1105 } 1106 } 1107 } 1108 1109 mmc_release_host(test->card->host); 1110 1111 printk(KERN_INFO "%s: Tests completed.\n", 1112 mmc_hostname(test->card->host)); 1113} 1114 1115static ssize_t mmc_test_show(struct device *dev, 1116 struct device_attribute *attr, char *buf) 1117{ 1118 mutex_lock(&mmc_test_lock); 1119 mutex_unlock(&mmc_test_lock); 1120 1121 return 0; 1122} 1123 1124static ssize_t mmc_test_store(struct device *dev, 1125 struct device_attribute *attr, const char *buf, size_t count) 1126{ 1127 struct mmc_card *card; 1128 struct mmc_test_card *test; 1129 int testcase; 1130 1131 card = container_of(dev, struct mmc_card, dev); 1132 1133 testcase = simple_strtol(buf, NULL, 10); 1134 1135 test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL); 1136 if (!test) 1137 return -ENOMEM; 1138 1139 test->card = card; 1140 1141 test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL); 1142#ifdef CONFIG_HIGHMEM 1143 test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER); 1144#endif 1145 1146#ifdef CONFIG_HIGHMEM 1147 if (test->buffer && test->highmem) { 1148#else 1149 if (test->buffer) { 1150#endif 1151 mutex_lock(&mmc_test_lock); 1152 mmc_test_run(test, testcase); 1153 mutex_unlock(&mmc_test_lock); 1154 } 1155 1156#ifdef CONFIG_HIGHMEM 1157 __free_pages(test->highmem, BUFFER_ORDER); 1158#endif 1159 kfree(test->buffer); 1160 kfree(test); 1161 1162 return count; 1163} 1164 1165static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store); 1166 1167static int mmc_test_probe(struct mmc_card *card) 1168{ 1169 int ret; 1170 1171 if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD)) 1172 return -ENODEV; 1173 1174 mutex_init(&mmc_test_lock); 1175 1176 ret = device_create_file(&card->dev, &dev_attr_test); 1177 if (ret) 1178 return ret; 1179 1180 dev_info(&card->dev, "Card claimed for testing.\n"); 1181 1182 return 0; 1183} 1184 1185static void mmc_test_remove(struct mmc_card *card) 1186{ 1187 device_remove_file(&card->dev, &dev_attr_test); 1188} 1189 1190static struct mmc_driver mmc_driver = { 1191 .drv = { 1192 .name = "mmc_test", 1193 }, 1194 .probe = mmc_test_probe, 1195 .remove = mmc_test_remove, 1196}; 1197 1198static int __init mmc_test_init(void) 1199{ 1200 return mmc_register_driver(&mmc_driver); 1201} 1202 1203static void __exit mmc_test_exit(void) 1204{ 1205 mmc_unregister_driver(&mmc_driver); 1206} 1207 1208module_init(mmc_test_init); 1209module_exit(mmc_test_exit); 1210 1211MODULE_LICENSE("GPL"); 1212MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver"); 1213MODULE_AUTHOR("Pierre Ossman"); 1214