mmc_test.c 27 KB

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