]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/mmc/card/mmc_test.c
mmc: mmc host test driver
[linux-2.6-omap-h63xx.git] / drivers / mmc / card / mmc_test.c
1 /*
2  *  linux/drivers/mmc/card/mmc_test.c
3  *
4  *  Copyright 2007 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_SIZE     (PAGE_SIZE * 4)
25
26 struct mmc_test_card {
27         struct mmc_card *card;
28
29         u8              *buffer;
30 };
31
32 /*******************************************************************/
33 /*  Helper functions                                               */
34 /*******************************************************************/
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
41         cmd.opcode = MMC_SET_BLOCKLEN;
42         cmd.arg = size;
43         cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
44         ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
45         if (ret)
46                 return ret;
47
48         return 0;
49 }
50
51 static int __mmc_test_transfer(struct mmc_test_card *test, int write,
52         unsigned broken_xfer, u8 *buffer, unsigned addr,
53         unsigned blocks, unsigned blksz)
54 {
55         int ret, busy;
56
57         struct mmc_request mrq;
58         struct mmc_command cmd;
59         struct mmc_command stop;
60         struct mmc_data data;
61
62         struct scatterlist sg;
63
64         memset(&mrq, 0, sizeof(struct mmc_request));
65
66         mrq.cmd = &cmd;
67         mrq.data = &data;
68
69         memset(&cmd, 0, sizeof(struct mmc_command));
70
71         if (broken_xfer) {
72                 if (blocks > 1) {
73                         cmd.opcode = write ?
74                                 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
75                 } else {
76                         cmd.opcode = MMC_SEND_STATUS;
77                 }
78         } else {
79                 if (blocks > 1) {
80                         cmd.opcode = write ?
81                                 MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
82                 } else {
83                         cmd.opcode = write ?
84                                 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
85                 }
86         }
87
88         if (broken_xfer && blocks == 1)
89                 cmd.arg = test->card->rca << 16;
90         else
91                 cmd.arg = addr;
92         cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
93
94         memset(&stop, 0, sizeof(struct mmc_command));
95
96         if (!broken_xfer && (blocks > 1)) {
97                 stop.opcode = MMC_STOP_TRANSMISSION;
98                 stop.arg = 0;
99                 stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
100
101                 mrq.stop = &stop;
102         }
103
104         memset(&data, 0, sizeof(struct mmc_data));
105
106         data.blksz = blksz;
107         data.blocks = blocks;
108         data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
109         data.sg = &sg;
110         data.sg_len = 1;
111
112         sg_init_one(&sg, buffer, blocks * blksz);
113
114         mmc_set_data_timeout(&data, test->card);
115
116         mmc_wait_for_req(test->card->host, &mrq);
117
118         ret = 0;
119
120         if (broken_xfer) {
121                 if (!ret && cmd.error)
122                         ret = cmd.error;
123                 if (!ret && data.error == 0)
124                         ret = RESULT_FAIL;
125                 if (!ret && data.error != -ETIMEDOUT)
126                         ret = data.error;
127                 if (!ret && stop.error)
128                         ret = stop.error;
129                 if (blocks > 1) {
130                         if (!ret && data.bytes_xfered > blksz)
131                                 ret = RESULT_FAIL;
132                 } else {
133                         if (!ret && data.bytes_xfered > 0)
134                                 ret = RESULT_FAIL;
135                 }
136         } else {
137                 if (!ret && cmd.error)
138                         ret = cmd.error;
139                 if (!ret && data.error)
140                         ret = data.error;
141                 if (!ret && stop.error)
142                         ret = stop.error;
143                 if (!ret && data.bytes_xfered != blocks * blksz)
144                         ret = RESULT_FAIL;
145         }
146
147         if (ret == -EINVAL)
148                 ret = RESULT_UNSUP_HOST;
149
150         busy = 0;
151         do {
152                 int ret2;
153
154                 memset(&cmd, 0, sizeof(struct mmc_command));
155
156                 cmd.opcode = MMC_SEND_STATUS;
157                 cmd.arg = test->card->rca << 16;
158                 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
159
160                 ret2 = mmc_wait_for_cmd(test->card->host, &cmd, 0);
161                 if (ret2)
162                         break;
163
164                 if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
165                         busy = 1;
166                         printk(KERN_INFO "%s: Warning: Host did not "
167                                 "wait for busy state to end.\n",
168                                 mmc_hostname(test->card->host));
169                 }
170         } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
171
172         return ret;
173 }
174
175 static int mmc_test_transfer(struct mmc_test_card *test, int write,
176         u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz)
177 {
178         return __mmc_test_transfer(test, write, 0, buffer,
179                         addr, blocks, blksz);
180 }
181
182 static int mmc_test_prepare_verify(struct mmc_test_card *test, int write)
183 {
184         int ret, i;
185
186         ret = mmc_test_set_blksize(test, 512);
187         if (ret)
188                 return ret;
189
190         if (write)
191                 memset(test->buffer, 0xDF, BUFFER_SIZE);
192         else {
193                 for (i = 0;i < BUFFER_SIZE;i++)
194                         test->buffer[i] = i;
195         }
196
197         for (i = 0;i < BUFFER_SIZE / 512;i++) {
198                 ret = mmc_test_transfer(test, 1, test->buffer + i * 512,
199                         i * 512, 1, 512);
200                 if (ret)
201                         return ret;
202         }
203
204         return 0;
205 }
206
207 static int mmc_test_prepare_verify_write(struct mmc_test_card *test)
208 {
209         return mmc_test_prepare_verify(test, 1);
210 }
211
212 static int mmc_test_prepare_verify_read(struct mmc_test_card *test)
213 {
214         return mmc_test_prepare_verify(test, 0);
215 }
216
217 static int mmc_test_verified_transfer(struct mmc_test_card *test, int write,
218         u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz)
219 {
220         int ret, i, sectors;
221
222         /*
223          * It is assumed that the above preparation has been done.
224          */
225
226         memset(test->buffer, 0, BUFFER_SIZE);
227
228         if (write) {
229                 for (i = 0;i < blocks * blksz;i++)
230                         buffer[i] = i;
231         }
232
233         ret = mmc_test_set_blksize(test, blksz);
234         if (ret)
235                 return ret;
236
237         ret = mmc_test_transfer(test, write, buffer, addr, blocks, blksz);
238         if (ret)
239                 return ret;
240
241         if (write) {
242                 ret = mmc_test_set_blksize(test, 512);
243                 if (ret)
244                         return ret;
245
246                 sectors = (blocks * blksz + 511) / 512;
247                 if ((sectors * 512) == (blocks * blksz))
248                         sectors++;
249
250                 if ((sectors * 512) > BUFFER_SIZE)
251                         return -EINVAL;
252
253                 memset(test->buffer, 0, sectors * 512);
254
255                 for (i = 0;i < sectors;i++) {
256                         ret = mmc_test_transfer(test, 0,
257                                 test->buffer + i * 512,
258                                 addr + i * 512, 1, 512);
259                         if (ret)
260                                 return ret;
261                 }
262
263                 for (i = 0;i < blocks * blksz;i++) {
264                         if (test->buffer[i] != (u8)i)
265                                 return RESULT_FAIL;
266                 }
267
268                 for (;i < sectors * 512;i++) {
269                         if (test->buffer[i] != 0xDF)
270                                 return RESULT_FAIL;
271                 }
272         } else {
273                 for (i = 0;i < blocks * blksz;i++) {
274                         if (buffer[i] != (u8)i)
275                                 return RESULT_FAIL;
276                 }
277         }
278
279         return 0;
280 }
281
282 static int mmc_test_cleanup_verify(struct mmc_test_card *test)
283 {
284         int ret, i;
285
286         ret = mmc_test_set_blksize(test, 512);
287         if (ret)
288                 return ret;
289
290         memset(test->buffer, 0, BUFFER_SIZE);
291
292         for (i = 0;i < BUFFER_SIZE / 512;i++) {
293                 ret = mmc_test_transfer(test, 1, test->buffer + i * 512,
294                         i * 512, 1, 512);
295                 if (ret)
296                         return ret;
297         }
298
299         return 0;
300 }
301
302 /*******************************************************************/
303 /*  Tests                                                          */
304 /*******************************************************************/
305
306 struct mmc_test_case {
307         const char *name;
308
309         int (*prepare)(struct mmc_test_card *);
310         int (*run)(struct mmc_test_card *);
311         int (*cleanup)(struct mmc_test_card *);
312 };
313
314 static int mmc_test_basic_write(struct mmc_test_card *test)
315 {
316         int ret;
317
318         ret = mmc_test_set_blksize(test, 512);
319         if (ret)
320                 return ret;
321
322         ret = mmc_test_transfer(test, 1, test->buffer, 0, 1, 512);
323         if (ret)
324                 return ret;
325
326         return 0;
327 }
328
329 static int mmc_test_basic_read(struct mmc_test_card *test)
330 {
331         int ret;
332
333         ret = mmc_test_set_blksize(test, 512);
334         if (ret)
335                 return ret;
336
337         ret = mmc_test_transfer(test, 0, test->buffer, 0, 1, 512);
338         if (ret)
339                 return ret;
340
341         return 0;
342 }
343
344 static int mmc_test_verify_write(struct mmc_test_card *test)
345 {
346         int ret;
347
348         ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, 512);
349         if (ret)
350                 return ret;
351
352         return 0;
353 }
354
355 static int mmc_test_verify_read(struct mmc_test_card *test)
356 {
357         int ret;
358
359         ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, 512);
360         if (ret)
361                 return ret;
362
363         return 0;
364 }
365
366 static int mmc_test_multi_write(struct mmc_test_card *test)
367 {
368         int ret;
369         unsigned int size;
370
371         if (test->card->host->max_blk_count == 1)
372                 return RESULT_UNSUP_HOST;
373
374         size = PAGE_SIZE * 2;
375         size = min(size, test->card->host->max_req_size);
376         size = min(size, test->card->host->max_seg_size);
377         size = min(size, test->card->host->max_blk_count * 512);
378
379         if (size < 1024)
380                 return RESULT_UNSUP_HOST;
381
382         ret = mmc_test_verified_transfer(test, 1, test->buffer, 0,
383                 size / 512, 512);
384         if (ret)
385                 return ret;
386
387         return 0;
388 }
389
390 static int mmc_test_multi_read(struct mmc_test_card *test)
391 {
392         int ret;
393         unsigned int size;
394
395         if (test->card->host->max_blk_count == 1)
396                 return RESULT_UNSUP_HOST;
397
398         size = PAGE_SIZE * 2;
399         size = min(size, test->card->host->max_req_size);
400         size = min(size, test->card->host->max_seg_size);
401         size = min(size, test->card->host->max_blk_count * 512);
402
403         if (size < 1024)
404                 return RESULT_UNSUP_HOST;
405
406         ret = mmc_test_verified_transfer(test, 0, test->buffer, 0,
407                 size / 512, 512);
408         if (ret)
409                 return ret;
410
411         return 0;
412 }
413
414 static int mmc_test_pow2_write(struct mmc_test_card *test)
415 {
416         int ret, i;
417
418         if (!test->card->csd.write_partial)
419                 return RESULT_UNSUP_CARD;
420
421         for (i = 1; i < 512;i <<= 1) {
422                 ret = mmc_test_verified_transfer(test, 1,
423                         test->buffer, 0, 1, i);
424                 if (ret)
425                         return ret;
426         }
427
428         return 0;
429 }
430
431 static int mmc_test_pow2_read(struct mmc_test_card *test)
432 {
433         int ret, i;
434
435         if (!test->card->csd.read_partial)
436                 return RESULT_UNSUP_CARD;
437
438         for (i = 1; i < 512;i <<= 1) {
439                 ret = mmc_test_verified_transfer(test, 0,
440                         test->buffer, 0, 1, i);
441                 if (ret)
442                         return ret;
443         }
444
445         return 0;
446 }
447
448 static int mmc_test_weird_write(struct mmc_test_card *test)
449 {
450         int ret, i;
451
452         if (!test->card->csd.write_partial)
453                 return RESULT_UNSUP_CARD;
454
455         for (i = 3; i < 512;i += 7) {
456                 ret = mmc_test_verified_transfer(test, 1,
457                         test->buffer, 0, 1, i);
458                 if (ret)
459                         return ret;
460         }
461
462         return 0;
463 }
464
465 static int mmc_test_weird_read(struct mmc_test_card *test)
466 {
467         int ret, i;
468
469         if (!test->card->csd.read_partial)
470                 return RESULT_UNSUP_CARD;
471
472         for (i = 3; i < 512;i += 7) {
473                 ret = mmc_test_verified_transfer(test, 0,
474                         test->buffer, 0, 1, i);
475                 if (ret)
476                         return ret;
477         }
478
479         return 0;
480 }
481
482 static int mmc_test_align_write(struct mmc_test_card *test)
483 {
484         int ret, i;
485
486         for (i = 1;i < 4;i++) {
487                 ret = mmc_test_verified_transfer(test, 1, test->buffer + i,
488                         0, 1, 512);
489                 if (ret)
490                         return ret;
491         }
492
493         return 0;
494 }
495
496 static int mmc_test_align_read(struct mmc_test_card *test)
497 {
498         int ret, i;
499
500         for (i = 1;i < 4;i++) {
501                 ret = mmc_test_verified_transfer(test, 0, test->buffer + i,
502                         0, 1, 512);
503                 if (ret)
504                         return ret;
505         }
506
507         return 0;
508 }
509
510 static int mmc_test_align_multi_write(struct mmc_test_card *test)
511 {
512         int ret, i;
513         unsigned int size;
514
515         if (test->card->host->max_blk_count == 1)
516                 return RESULT_UNSUP_HOST;
517
518         size = PAGE_SIZE * 2;
519         size = min(size, test->card->host->max_req_size);
520         size = min(size, test->card->host->max_seg_size);
521         size = min(size, test->card->host->max_blk_count * 512);
522
523         if (size < 1024)
524                 return RESULT_UNSUP_HOST;
525
526         for (i = 1;i < 4;i++) {
527                 ret = mmc_test_verified_transfer(test, 1, test->buffer + i,
528                         0, size / 512, 512);
529                 if (ret)
530                         return ret;
531         }
532
533         return 0;
534 }
535
536 static int mmc_test_align_multi_read(struct mmc_test_card *test)
537 {
538         int ret, i;
539         unsigned int size;
540
541         if (test->card->host->max_blk_count == 1)
542                 return RESULT_UNSUP_HOST;
543
544         size = PAGE_SIZE * 2;
545         size = min(size, test->card->host->max_req_size);
546         size = min(size, test->card->host->max_seg_size);
547         size = min(size, test->card->host->max_blk_count * 512);
548
549         if (size < 1024)
550                 return RESULT_UNSUP_HOST;
551
552         for (i = 1;i < 4;i++) {
553                 ret = mmc_test_verified_transfer(test, 0, test->buffer + i,
554                         0, size / 512, 512);
555                 if (ret)
556                         return ret;
557         }
558
559         return 0;
560 }
561
562 static int mmc_test_xfersize_write(struct mmc_test_card *test)
563 {
564         int ret;
565
566         ret = mmc_test_set_blksize(test, 512);
567         if (ret)
568                 return ret;
569
570         ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 1, 512);
571         if (ret)
572                 return ret;
573
574         return 0;
575 }
576
577 static int mmc_test_xfersize_read(struct mmc_test_card *test)
578 {
579         int ret;
580
581         ret = mmc_test_set_blksize(test, 512);
582         if (ret)
583                 return ret;
584
585         ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 1, 512);
586         if (ret)
587                 return ret;
588
589         return 0;
590 }
591
592 static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
593 {
594         int ret;
595
596         if (test->card->host->max_blk_count == 1)
597                 return RESULT_UNSUP_HOST;
598
599         ret = mmc_test_set_blksize(test, 512);
600         if (ret)
601                 return ret;
602
603         ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 2, 512);
604         if (ret)
605                 return ret;
606
607         return 0;
608 }
609
610 static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
611 {
612         int ret;
613
614         if (test->card->host->max_blk_count == 1)
615                 return RESULT_UNSUP_HOST;
616
617         ret = mmc_test_set_blksize(test, 512);
618         if (ret)
619                 return ret;
620
621         ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 2, 512);
622         if (ret)
623                 return ret;
624
625         return 0;
626 }
627
628 static const struct mmc_test_case mmc_test_cases[] = {
629         {
630                 .name = "Basic write (no data verification)",
631                 .run = mmc_test_basic_write,
632         },
633
634         {
635                 .name = "Basic read (no data verification)",
636                 .run = mmc_test_basic_read,
637         },
638
639         {
640                 .name = "Basic write (with data verification)",
641                 .prepare = mmc_test_prepare_verify_write,
642                 .run = mmc_test_verify_write,
643                 .cleanup = mmc_test_cleanup_verify,
644         },
645
646         {
647                 .name = "Basic read (with data verification)",
648                 .prepare = mmc_test_prepare_verify_read,
649                 .run = mmc_test_verify_read,
650                 .cleanup = mmc_test_cleanup_verify,
651         },
652
653         {
654                 .name = "Multi-block write",
655                 .prepare = mmc_test_prepare_verify_write,
656                 .run = mmc_test_multi_write,
657                 .cleanup = mmc_test_cleanup_verify,
658         },
659
660         {
661                 .name = "Multi-block read",
662                 .prepare = mmc_test_prepare_verify_read,
663                 .run = mmc_test_multi_read,
664                 .cleanup = mmc_test_cleanup_verify,
665         },
666
667         {
668                 .name = "Power of two block writes",
669                 .prepare = mmc_test_prepare_verify_write,
670                 .run = mmc_test_pow2_write,
671                 .cleanup = mmc_test_cleanup_verify,
672         },
673
674         {
675                 .name = "Power of two block reads",
676                 .prepare = mmc_test_prepare_verify_read,
677                 .run = mmc_test_pow2_read,
678                 .cleanup = mmc_test_cleanup_verify,
679         },
680
681         {
682                 .name = "Weird sized block writes",
683                 .prepare = mmc_test_prepare_verify_write,
684                 .run = mmc_test_weird_write,
685                 .cleanup = mmc_test_cleanup_verify,
686         },
687
688         {
689                 .name = "Weird sized block reads",
690                 .prepare = mmc_test_prepare_verify_read,
691                 .run = mmc_test_weird_read,
692                 .cleanup = mmc_test_cleanup_verify,
693         },
694
695         {
696                 .name = "Badly aligned write",
697                 .prepare = mmc_test_prepare_verify_write,
698                 .run = mmc_test_align_write,
699                 .cleanup = mmc_test_cleanup_verify,
700         },
701
702         {
703                 .name = "Badly aligned read",
704                 .prepare = mmc_test_prepare_verify_read,
705                 .run = mmc_test_align_read,
706                 .cleanup = mmc_test_cleanup_verify,
707         },
708
709         {
710                 .name = "Badly aligned multi-block write",
711                 .prepare = mmc_test_prepare_verify_write,
712                 .run = mmc_test_align_multi_write,
713                 .cleanup = mmc_test_cleanup_verify,
714         },
715
716         {
717                 .name = "Badly aligned multi-block read",
718                 .prepare = mmc_test_prepare_verify_read,
719                 .run = mmc_test_align_multi_read,
720                 .cleanup = mmc_test_cleanup_verify,
721         },
722
723         {
724                 .name = "Correct xfer_size at write (start failure)",
725                 .run = mmc_test_xfersize_write,
726         },
727
728         {
729                 .name = "Correct xfer_size at read (start failure)",
730                 .run = mmc_test_xfersize_read,
731         },
732
733         {
734                 .name = "Correct xfer_size at write (midway failure)",
735                 .run = mmc_test_multi_xfersize_write,
736         },
737
738         {
739                 .name = "Correct xfer_size at read (midway failure)",
740                 .run = mmc_test_multi_xfersize_read,
741         },
742 };
743
744 static struct mutex mmc_test_lock;
745
746 static void mmc_test_run(struct mmc_test_card *test)
747 {
748         int i, ret;
749
750         printk(KERN_INFO "%s: Starting tests of card %s...\n",
751                 mmc_hostname(test->card->host), mmc_card_id(test->card));
752
753         mmc_claim_host(test->card->host);
754
755         for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
756                 printk(KERN_INFO "%s: Test case %d. %s...\n",
757                         mmc_hostname(test->card->host), i + 1,
758                         mmc_test_cases[i].name);
759
760                 if (mmc_test_cases[i].prepare) {
761                         ret = mmc_test_cases[i].prepare(test);
762                         if (ret) {
763                                 printk(KERN_INFO "%s: Result: Prepare "
764                                         "stage failed! (%d)\n",
765                                         mmc_hostname(test->card->host),
766                                         ret);
767                                 continue;
768                         }
769                 }
770
771                 ret = mmc_test_cases[i].run(test);
772                 switch (ret) {
773                 case RESULT_OK:
774                         printk(KERN_INFO "%s: Result: OK\n",
775                                 mmc_hostname(test->card->host));
776                         break;
777                 case RESULT_FAIL:
778                         printk(KERN_INFO "%s: Result: FAILED\n",
779                                 mmc_hostname(test->card->host));
780                         break;
781                 case RESULT_UNSUP_HOST:
782                         printk(KERN_INFO "%s: Result: UNSUPPORTED "
783                                 "(by host)\n",
784                                 mmc_hostname(test->card->host));
785                         break;
786                 case RESULT_UNSUP_CARD:
787                         printk(KERN_INFO "%s: Result: UNSUPPORTED "
788                                 "(by card)\n",
789                                 mmc_hostname(test->card->host));
790                         break;
791                 default:
792                         printk(KERN_INFO "%s: Result: ERROR (%d)\n",
793                                 mmc_hostname(test->card->host), ret);
794                 }
795
796                 if (mmc_test_cases[i].cleanup) {
797                         ret = mmc_test_cases[i].cleanup(test);
798                         if (ret) {
799                                 printk(KERN_INFO "%s: Warning: Cleanup "
800                                         "stage failed! (%d)\n",
801                                         mmc_hostname(test->card->host),
802                                         ret);
803                         }
804                 }
805         }
806
807         mmc_release_host(test->card->host);
808
809         printk(KERN_INFO "%s: Tests completed.\n",
810                 mmc_hostname(test->card->host));
811 }
812
813 static ssize_t mmc_test_show(struct device *dev,
814         struct device_attribute *attr, char *buf)
815 {
816         mutex_lock(&mmc_test_lock);
817         mutex_unlock(&mmc_test_lock);
818
819         return 0;
820 }
821
822 static ssize_t mmc_test_store(struct device *dev,
823         struct device_attribute *attr, const char *buf, size_t count)
824 {
825         struct mmc_card *card;
826         struct mmc_test_card *test;
827
828         card = container_of(dev, struct mmc_card, dev);
829
830         test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
831         if (!test)
832                 return -ENOMEM;
833
834         test->card = card;
835
836         test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
837         if (test->buffer) {
838                 mutex_lock(&mmc_test_lock);
839                 mmc_test_run(test);
840                 mutex_unlock(&mmc_test_lock);
841         }
842
843         kfree(test->buffer);
844         kfree(test);
845
846         return count;
847 }
848
849 static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store);
850
851 static int mmc_test_probe(struct mmc_card *card)
852 {
853         int ret;
854
855         mutex_init(&mmc_test_lock);
856
857         ret = device_create_file(&card->dev, &dev_attr_test);
858         if (ret)
859                 return ret;
860
861         return 0;
862 }
863
864 static void mmc_test_remove(struct mmc_card *card)
865 {
866         device_remove_file(&card->dev, &dev_attr_test);
867 }
868
869 static struct mmc_driver mmc_driver = {
870         .drv            = {
871                 .name   = "mmc_test",
872         },
873         .probe          = mmc_test_probe,
874         .remove         = mmc_test_remove,
875 };
876
877 static int __init mmc_test_init(void)
878 {
879         return mmc_register_driver(&mmc_driver);
880 }
881
882 static void __exit mmc_test_exit(void)
883 {
884         mmc_unregister_driver(&mmc_driver);
885 }
886
887 module_init(mmc_test_init);
888 module_exit(mmc_test_exit);
889
890 MODULE_LICENSE("GPL");
891 MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver");
892 MODULE_AUTHOR("Pierre Ossman");