mmc_test.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  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. if (write) {
  313. for (i = 0;i < blocks * blksz;i++)
  314. test->scratch[i] = i;
  315. } else {
  316. memset(test->scratch, 0, BUFFER_SIZE);
  317. }
  318. local_irq_save(flags);
  319. sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
  320. local_irq_restore(flags);
  321. ret = mmc_test_set_blksize(test, blksz);
  322. if (ret)
  323. return ret;
  324. ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr,
  325. blocks, blksz, write);
  326. if (ret)
  327. return ret;
  328. if (write) {
  329. int sectors;
  330. ret = mmc_test_set_blksize(test, 512);
  331. if (ret)
  332. return ret;
  333. sectors = (blocks * blksz + 511) / 512;
  334. if ((sectors * 512) == (blocks * blksz))
  335. sectors++;
  336. if ((sectors * 512) > BUFFER_SIZE)
  337. return -EINVAL;
  338. memset(test->buffer, 0, sectors * 512);
  339. for (i = 0;i < sectors;i++) {
  340. ret = mmc_test_buffer_transfer(test,
  341. test->buffer + i * 512,
  342. dev_addr + i * 512, 512, 0);
  343. if (ret)
  344. return ret;
  345. }
  346. for (i = 0;i < blocks * blksz;i++) {
  347. if (test->buffer[i] != (u8)i)
  348. return RESULT_FAIL;
  349. }
  350. for (;i < sectors * 512;i++) {
  351. if (test->buffer[i] != 0xDF)
  352. return RESULT_FAIL;
  353. }
  354. } else {
  355. local_irq_save(flags);
  356. sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
  357. local_irq_restore(flags);
  358. for (i = 0;i < blocks * blksz;i++) {
  359. if (test->scratch[i] != (u8)i)
  360. return RESULT_FAIL;
  361. }
  362. }
  363. return 0;
  364. }
  365. /*******************************************************************/
  366. /* Tests */
  367. /*******************************************************************/
  368. struct mmc_test_case {
  369. const char *name;
  370. int (*prepare)(struct mmc_test_card *);
  371. int (*run)(struct mmc_test_card *);
  372. int (*cleanup)(struct mmc_test_card *);
  373. };
  374. static int mmc_test_basic_write(struct mmc_test_card *test)
  375. {
  376. int ret;
  377. struct scatterlist sg;
  378. ret = mmc_test_set_blksize(test, 512);
  379. if (ret)
  380. return ret;
  381. sg_init_one(&sg, test->buffer, 512);
  382. ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
  383. if (ret)
  384. return ret;
  385. return 0;
  386. }
  387. static int mmc_test_basic_read(struct mmc_test_card *test)
  388. {
  389. int ret;
  390. struct scatterlist sg;
  391. ret = mmc_test_set_blksize(test, 512);
  392. if (ret)
  393. return ret;
  394. sg_init_one(&sg, test->buffer, 512);
  395. ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
  396. if (ret)
  397. return ret;
  398. return 0;
  399. }
  400. static int mmc_test_verify_write(struct mmc_test_card *test)
  401. {
  402. int ret;
  403. struct scatterlist sg;
  404. sg_init_one(&sg, test->buffer, 512);
  405. ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
  406. if (ret)
  407. return ret;
  408. return 0;
  409. }
  410. static int mmc_test_verify_read(struct mmc_test_card *test)
  411. {
  412. int ret;
  413. struct scatterlist sg;
  414. sg_init_one(&sg, test->buffer, 512);
  415. ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
  416. if (ret)
  417. return ret;
  418. return 0;
  419. }
  420. static int mmc_test_multi_write(struct mmc_test_card *test)
  421. {
  422. int ret;
  423. unsigned int size;
  424. struct scatterlist sg;
  425. if (test->card->host->max_blk_count == 1)
  426. return RESULT_UNSUP_HOST;
  427. size = PAGE_SIZE * 2;
  428. size = min(size, test->card->host->max_req_size);
  429. size = min(size, test->card->host->max_seg_size);
  430. size = min(size, test->card->host->max_blk_count * 512);
  431. if (size < 1024)
  432. return RESULT_UNSUP_HOST;
  433. sg_init_one(&sg, test->buffer, size);
  434. ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
  435. if (ret)
  436. return ret;
  437. return 0;
  438. }
  439. static int mmc_test_multi_read(struct mmc_test_card *test)
  440. {
  441. int ret;
  442. unsigned int size;
  443. struct scatterlist sg;
  444. if (test->card->host->max_blk_count == 1)
  445. return RESULT_UNSUP_HOST;
  446. size = PAGE_SIZE * 2;
  447. size = min(size, test->card->host->max_req_size);
  448. size = min(size, test->card->host->max_seg_size);
  449. size = min(size, test->card->host->max_blk_count * 512);
  450. if (size < 1024)
  451. return RESULT_UNSUP_HOST;
  452. sg_init_one(&sg, test->buffer, size);
  453. ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
  454. if (ret)
  455. return ret;
  456. return 0;
  457. }
  458. static int mmc_test_pow2_write(struct mmc_test_card *test)
  459. {
  460. int ret, i;
  461. struct scatterlist sg;
  462. if (!test->card->csd.write_partial)
  463. return RESULT_UNSUP_CARD;
  464. for (i = 1; i < 512;i <<= 1) {
  465. sg_init_one(&sg, test->buffer, i);
  466. ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
  467. if (ret)
  468. return ret;
  469. }
  470. return 0;
  471. }
  472. static int mmc_test_pow2_read(struct mmc_test_card *test)
  473. {
  474. int ret, i;
  475. struct scatterlist sg;
  476. if (!test->card->csd.read_partial)
  477. return RESULT_UNSUP_CARD;
  478. for (i = 1; i < 512;i <<= 1) {
  479. sg_init_one(&sg, test->buffer, i);
  480. ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
  481. if (ret)
  482. return ret;
  483. }
  484. return 0;
  485. }
  486. static int mmc_test_weird_write(struct mmc_test_card *test)
  487. {
  488. int ret, i;
  489. struct scatterlist sg;
  490. if (!test->card->csd.write_partial)
  491. return RESULT_UNSUP_CARD;
  492. for (i = 3; i < 512;i += 7) {
  493. sg_init_one(&sg, test->buffer, i);
  494. ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
  495. if (ret)
  496. return ret;
  497. }
  498. return 0;
  499. }
  500. static int mmc_test_weird_read(struct mmc_test_card *test)
  501. {
  502. int ret, i;
  503. struct scatterlist sg;
  504. if (!test->card->csd.read_partial)
  505. return RESULT_UNSUP_CARD;
  506. for (i = 3; i < 512;i += 7) {
  507. sg_init_one(&sg, test->buffer, i);
  508. ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
  509. if (ret)
  510. return ret;
  511. }
  512. return 0;
  513. }
  514. static int mmc_test_align_write(struct mmc_test_card *test)
  515. {
  516. int ret, i;
  517. struct scatterlist sg;
  518. for (i = 1;i < 4;i++) {
  519. sg_init_one(&sg, test->buffer + i, 512);
  520. ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
  521. if (ret)
  522. return ret;
  523. }
  524. return 0;
  525. }
  526. static int mmc_test_align_read(struct mmc_test_card *test)
  527. {
  528. int ret, i;
  529. struct scatterlist sg;
  530. for (i = 1;i < 4;i++) {
  531. sg_init_one(&sg, test->buffer + i, 512);
  532. ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
  533. if (ret)
  534. return ret;
  535. }
  536. return 0;
  537. }
  538. static int mmc_test_align_multi_write(struct mmc_test_card *test)
  539. {
  540. int ret, i;
  541. unsigned int size;
  542. struct scatterlist sg;
  543. if (test->card->host->max_blk_count == 1)
  544. return RESULT_UNSUP_HOST;
  545. size = PAGE_SIZE * 2;
  546. size = min(size, test->card->host->max_req_size);
  547. size = min(size, test->card->host->max_seg_size);
  548. size = min(size, test->card->host->max_blk_count * 512);
  549. if (size < 1024)
  550. return RESULT_UNSUP_HOST;
  551. for (i = 1;i < 4;i++) {
  552. sg_init_one(&sg, test->buffer + i, size);
  553. ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
  554. if (ret)
  555. return ret;
  556. }
  557. return 0;
  558. }
  559. static int mmc_test_align_multi_read(struct mmc_test_card *test)
  560. {
  561. int ret, i;
  562. unsigned int size;
  563. struct scatterlist sg;
  564. if (test->card->host->max_blk_count == 1)
  565. return RESULT_UNSUP_HOST;
  566. size = PAGE_SIZE * 2;
  567. size = min(size, test->card->host->max_req_size);
  568. size = min(size, test->card->host->max_seg_size);
  569. size = min(size, test->card->host->max_blk_count * 512);
  570. if (size < 1024)
  571. return RESULT_UNSUP_HOST;
  572. for (i = 1;i < 4;i++) {
  573. sg_init_one(&sg, test->buffer + i, size);
  574. ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
  575. if (ret)
  576. return ret;
  577. }
  578. return 0;
  579. }
  580. static int mmc_test_xfersize_write(struct mmc_test_card *test)
  581. {
  582. int ret;
  583. ret = mmc_test_set_blksize(test, 512);
  584. if (ret)
  585. return ret;
  586. ret = mmc_test_broken_transfer(test, 1, 512, 1);
  587. if (ret)
  588. return ret;
  589. return 0;
  590. }
  591. static int mmc_test_xfersize_read(struct mmc_test_card *test)
  592. {
  593. int ret;
  594. ret = mmc_test_set_blksize(test, 512);
  595. if (ret)
  596. return ret;
  597. ret = mmc_test_broken_transfer(test, 1, 512, 0);
  598. if (ret)
  599. return ret;
  600. return 0;
  601. }
  602. static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
  603. {
  604. int ret;
  605. if (test->card->host->max_blk_count == 1)
  606. return RESULT_UNSUP_HOST;
  607. ret = mmc_test_set_blksize(test, 512);
  608. if (ret)
  609. return ret;
  610. ret = mmc_test_broken_transfer(test, 2, 512, 1);
  611. if (ret)
  612. return ret;
  613. return 0;
  614. }
  615. static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
  616. {
  617. int ret;
  618. if (test->card->host->max_blk_count == 1)
  619. return RESULT_UNSUP_HOST;
  620. ret = mmc_test_set_blksize(test, 512);
  621. if (ret)
  622. return ret;
  623. ret = mmc_test_broken_transfer(test, 2, 512, 0);
  624. if (ret)
  625. return ret;
  626. return 0;
  627. }
  628. #ifdef CONFIG_HIGHMEM
  629. static int mmc_test_write_high(struct mmc_test_card *test)
  630. {
  631. int ret;
  632. struct scatterlist sg;
  633. sg_init_table(&sg, 1);
  634. sg_set_page(&sg, test->highmem, 512, 0);
  635. ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
  636. if (ret)
  637. return ret;
  638. return 0;
  639. }
  640. static int mmc_test_read_high(struct mmc_test_card *test)
  641. {
  642. int ret;
  643. struct scatterlist sg;
  644. sg_init_table(&sg, 1);
  645. sg_set_page(&sg, test->highmem, 512, 0);
  646. ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
  647. if (ret)
  648. return ret;
  649. return 0;
  650. }
  651. static int mmc_test_multi_write_high(struct mmc_test_card *test)
  652. {
  653. int ret;
  654. unsigned int size;
  655. struct scatterlist sg;
  656. if (test->card->host->max_blk_count == 1)
  657. return RESULT_UNSUP_HOST;
  658. size = PAGE_SIZE * 2;
  659. size = min(size, test->card->host->max_req_size);
  660. size = min(size, test->card->host->max_seg_size);
  661. size = min(size, test->card->host->max_blk_count * 512);
  662. if (size < 1024)
  663. return RESULT_UNSUP_HOST;
  664. sg_init_table(&sg, 1);
  665. sg_set_page(&sg, test->highmem, size, 0);
  666. ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
  667. if (ret)
  668. return ret;
  669. return 0;
  670. }
  671. static int mmc_test_multi_read_high(struct mmc_test_card *test)
  672. {
  673. int ret;
  674. unsigned int size;
  675. struct scatterlist sg;
  676. if (test->card->host->max_blk_count == 1)
  677. return RESULT_UNSUP_HOST;
  678. size = PAGE_SIZE * 2;
  679. size = min(size, test->card->host->max_req_size);
  680. size = min(size, test->card->host->max_seg_size);
  681. size = min(size, test->card->host->max_blk_count * 512);
  682. if (size < 1024)
  683. return RESULT_UNSUP_HOST;
  684. sg_init_table(&sg, 1);
  685. sg_set_page(&sg, test->highmem, size, 0);
  686. ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
  687. if (ret)
  688. return ret;
  689. return 0;
  690. }
  691. #endif /* CONFIG_HIGHMEM */
  692. static const struct mmc_test_case mmc_test_cases[] = {
  693. {
  694. .name = "Basic write (no data verification)",
  695. .run = mmc_test_basic_write,
  696. },
  697. {
  698. .name = "Basic read (no data verification)",
  699. .run = mmc_test_basic_read,
  700. },
  701. {
  702. .name = "Basic write (with data verification)",
  703. .prepare = mmc_test_prepare_write,
  704. .run = mmc_test_verify_write,
  705. .cleanup = mmc_test_cleanup,
  706. },
  707. {
  708. .name = "Basic read (with data verification)",
  709. .prepare = mmc_test_prepare_read,
  710. .run = mmc_test_verify_read,
  711. .cleanup = mmc_test_cleanup,
  712. },
  713. {
  714. .name = "Multi-block write",
  715. .prepare = mmc_test_prepare_write,
  716. .run = mmc_test_multi_write,
  717. .cleanup = mmc_test_cleanup,
  718. },
  719. {
  720. .name = "Multi-block read",
  721. .prepare = mmc_test_prepare_read,
  722. .run = mmc_test_multi_read,
  723. .cleanup = mmc_test_cleanup,
  724. },
  725. {
  726. .name = "Power of two block writes",
  727. .prepare = mmc_test_prepare_write,
  728. .run = mmc_test_pow2_write,
  729. .cleanup = mmc_test_cleanup,
  730. },
  731. {
  732. .name = "Power of two block reads",
  733. .prepare = mmc_test_prepare_read,
  734. .run = mmc_test_pow2_read,
  735. .cleanup = mmc_test_cleanup,
  736. },
  737. {
  738. .name = "Weird sized block writes",
  739. .prepare = mmc_test_prepare_write,
  740. .run = mmc_test_weird_write,
  741. .cleanup = mmc_test_cleanup,
  742. },
  743. {
  744. .name = "Weird sized block reads",
  745. .prepare = mmc_test_prepare_read,
  746. .run = mmc_test_weird_read,
  747. .cleanup = mmc_test_cleanup,
  748. },
  749. {
  750. .name = "Badly aligned write",
  751. .prepare = mmc_test_prepare_write,
  752. .run = mmc_test_align_write,
  753. .cleanup = mmc_test_cleanup,
  754. },
  755. {
  756. .name = "Badly aligned read",
  757. .prepare = mmc_test_prepare_read,
  758. .run = mmc_test_align_read,
  759. .cleanup = mmc_test_cleanup,
  760. },
  761. {
  762. .name = "Badly aligned multi-block write",
  763. .prepare = mmc_test_prepare_write,
  764. .run = mmc_test_align_multi_write,
  765. .cleanup = mmc_test_cleanup,
  766. },
  767. {
  768. .name = "Badly aligned multi-block read",
  769. .prepare = mmc_test_prepare_read,
  770. .run = mmc_test_align_multi_read,
  771. .cleanup = mmc_test_cleanup,
  772. },
  773. {
  774. .name = "Correct xfer_size at write (start failure)",
  775. .run = mmc_test_xfersize_write,
  776. },
  777. {
  778. .name = "Correct xfer_size at read (start failure)",
  779. .run = mmc_test_xfersize_read,
  780. },
  781. {
  782. .name = "Correct xfer_size at write (midway failure)",
  783. .run = mmc_test_multi_xfersize_write,
  784. },
  785. {
  786. .name = "Correct xfer_size at read (midway failure)",
  787. .run = mmc_test_multi_xfersize_read,
  788. },
  789. #ifdef CONFIG_HIGHMEM
  790. {
  791. .name = "Highmem write",
  792. .prepare = mmc_test_prepare_write,
  793. .run = mmc_test_write_high,
  794. .cleanup = mmc_test_cleanup,
  795. },
  796. {
  797. .name = "Highmem read",
  798. .prepare = mmc_test_prepare_read,
  799. .run = mmc_test_read_high,
  800. .cleanup = mmc_test_cleanup,
  801. },
  802. {
  803. .name = "Multi-block highmem write",
  804. .prepare = mmc_test_prepare_write,
  805. .run = mmc_test_multi_write_high,
  806. .cleanup = mmc_test_cleanup,
  807. },
  808. {
  809. .name = "Multi-block highmem read",
  810. .prepare = mmc_test_prepare_read,
  811. .run = mmc_test_multi_read_high,
  812. .cleanup = mmc_test_cleanup,
  813. },
  814. #endif /* CONFIG_HIGHMEM */
  815. };
  816. static DEFINE_MUTEX(mmc_test_lock);
  817. static void mmc_test_run(struct mmc_test_card *test, int testcase)
  818. {
  819. int i, ret;
  820. printk(KERN_INFO "%s: Starting tests of card %s...\n",
  821. mmc_hostname(test->card->host), mmc_card_id(test->card));
  822. mmc_claim_host(test->card->host);
  823. for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
  824. if (testcase && ((i + 1) != testcase))
  825. continue;
  826. printk(KERN_INFO "%s: Test case %d. %s...\n",
  827. mmc_hostname(test->card->host), i + 1,
  828. mmc_test_cases[i].name);
  829. if (mmc_test_cases[i].prepare) {
  830. ret = mmc_test_cases[i].prepare(test);
  831. if (ret) {
  832. printk(KERN_INFO "%s: Result: Prepare "
  833. "stage failed! (%d)\n",
  834. mmc_hostname(test->card->host),
  835. ret);
  836. continue;
  837. }
  838. }
  839. ret = mmc_test_cases[i].run(test);
  840. switch (ret) {
  841. case RESULT_OK:
  842. printk(KERN_INFO "%s: Result: OK\n",
  843. mmc_hostname(test->card->host));
  844. break;
  845. case RESULT_FAIL:
  846. printk(KERN_INFO "%s: Result: FAILED\n",
  847. mmc_hostname(test->card->host));
  848. break;
  849. case RESULT_UNSUP_HOST:
  850. printk(KERN_INFO "%s: Result: UNSUPPORTED "
  851. "(by host)\n",
  852. mmc_hostname(test->card->host));
  853. break;
  854. case RESULT_UNSUP_CARD:
  855. printk(KERN_INFO "%s: Result: UNSUPPORTED "
  856. "(by card)\n",
  857. mmc_hostname(test->card->host));
  858. break;
  859. default:
  860. printk(KERN_INFO "%s: Result: ERROR (%d)\n",
  861. mmc_hostname(test->card->host), ret);
  862. }
  863. if (mmc_test_cases[i].cleanup) {
  864. ret = mmc_test_cases[i].cleanup(test);
  865. if (ret) {
  866. printk(KERN_INFO "%s: Warning: Cleanup "
  867. "stage failed! (%d)\n",
  868. mmc_hostname(test->card->host),
  869. ret);
  870. }
  871. }
  872. }
  873. mmc_release_host(test->card->host);
  874. printk(KERN_INFO "%s: Tests completed.\n",
  875. mmc_hostname(test->card->host));
  876. }
  877. static ssize_t mmc_test_show(struct device *dev,
  878. struct device_attribute *attr, char *buf)
  879. {
  880. mutex_lock(&mmc_test_lock);
  881. mutex_unlock(&mmc_test_lock);
  882. return 0;
  883. }
  884. static ssize_t mmc_test_store(struct device *dev,
  885. struct device_attribute *attr, const char *buf, size_t count)
  886. {
  887. struct mmc_card *card;
  888. struct mmc_test_card *test;
  889. int testcase;
  890. card = container_of(dev, struct mmc_card, dev);
  891. testcase = simple_strtol(buf, NULL, 10);
  892. test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
  893. if (!test)
  894. return -ENOMEM;
  895. test->card = card;
  896. test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
  897. #ifdef CONFIG_HIGHMEM
  898. test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
  899. #endif
  900. #ifdef CONFIG_HIGHMEM
  901. if (test->buffer && test->highmem) {
  902. #else
  903. if (test->buffer) {
  904. #endif
  905. mutex_lock(&mmc_test_lock);
  906. mmc_test_run(test, testcase);
  907. mutex_unlock(&mmc_test_lock);
  908. }
  909. #ifdef CONFIG_HIGHMEM
  910. __free_pages(test->highmem, BUFFER_ORDER);
  911. #endif
  912. kfree(test->buffer);
  913. kfree(test);
  914. return count;
  915. }
  916. static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store);
  917. static int mmc_test_probe(struct mmc_card *card)
  918. {
  919. int ret;
  920. if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD))
  921. return -ENODEV;
  922. ret = device_create_file(&card->dev, &dev_attr_test);
  923. if (ret)
  924. return ret;
  925. dev_info(&card->dev, "Card claimed for testing.\n");
  926. return 0;
  927. }
  928. static void mmc_test_remove(struct mmc_card *card)
  929. {
  930. device_remove_file(&card->dev, &dev_attr_test);
  931. }
  932. static struct mmc_driver mmc_driver = {
  933. .drv = {
  934. .name = "mmc_test",
  935. },
  936. .probe = mmc_test_probe,
  937. .remove = mmc_test_remove,
  938. };
  939. static int __init mmc_test_init(void)
  940. {
  941. return mmc_register_driver(&mmc_driver);
  942. }
  943. static void __exit mmc_test_exit(void)
  944. {
  945. mmc_unregister_driver(&mmc_driver);
  946. }
  947. module_init(mmc_test_init);
  948. module_exit(mmc_test_exit);
  949. MODULE_LICENSE("GPL");
  950. MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver");
  951. MODULE_AUTHOR("Pierre Ossman");