linux/arch/x86/mm/testmmiotrace.c
<<
>>
Prefs
   1/*
   2 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
   3 */
   4#include <linux/module.h>
   5#include <linux/io.h>
   6#include <linux/mmiotrace.h>
   7
   8#define MODULE_NAME "testmmiotrace"
   9
  10static unsigned long mmio_address;
  11module_param(mmio_address, ulong, 0);
  12MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
  13                                "(or 8 MB if read_far is non-zero).");
  14
  15static unsigned long read_far = 0x400100;
  16module_param(read_far, ulong, 0);
  17MODULE_PARM_DESC(read_far, " Offset of a 32-bit read within 8 MB "
  18                                "(default: 0x400100).");
  19
  20static unsigned v16(unsigned i)
  21{
  22        return i * 12 + 7;
  23}
  24
  25static unsigned v32(unsigned i)
  26{
  27        return i * 212371 + 13;
  28}
  29
  30static void do_write_test(void __iomem *p)
  31{
  32        unsigned int i;
  33        pr_info(MODULE_NAME ": write test.\n");
  34        mmiotrace_printk("Write test.\n");
  35
  36        for (i = 0; i < 256; i++)
  37                iowrite8(i, p + i);
  38
  39        for (i = 1024; i < (5 * 1024); i += 2)
  40                iowrite16(v16(i), p + i);
  41
  42        for (i = (5 * 1024); i < (16 * 1024); i += 4)
  43                iowrite32(v32(i), p + i);
  44}
  45
  46static void do_read_test(void __iomem *p)
  47{
  48        unsigned int i;
  49        unsigned errs[3] = { 0 };
  50        pr_info(MODULE_NAME ": read test.\n");
  51        mmiotrace_printk("Read test.\n");
  52
  53        for (i = 0; i < 256; i++)
  54                if (ioread8(p + i) != i)
  55                        ++errs[0];
  56
  57        for (i = 1024; i < (5 * 1024); i += 2)
  58                if (ioread16(p + i) != v16(i))
  59                        ++errs[1];
  60
  61        for (i = (5 * 1024); i < (16 * 1024); i += 4)
  62                if (ioread32(p + i) != v32(i))
  63                        ++errs[2];
  64
  65        mmiotrace_printk("Read errors: 8-bit %d, 16-bit %d, 32-bit %d.\n",
  66                                                errs[0], errs[1], errs[2]);
  67}
  68
  69static void do_read_far_test(void __iomem *p)
  70{
  71        pr_info(MODULE_NAME ": read far test.\n");
  72        mmiotrace_printk("Read far test.\n");
  73
  74        ioread32(p + read_far);
  75}
  76
  77static void do_test(unsigned long size)
  78{
  79        void __iomem *p = ioremap_nocache(mmio_address, size);
  80        if (!p) {
  81                pr_err(MODULE_NAME ": could not ioremap, aborting.\n");
  82                return;
  83        }
  84        mmiotrace_printk("ioremap returned %p.\n", p);
  85        do_write_test(p);
  86        do_read_test(p);
  87        if (read_far && read_far < size - 4)
  88                do_read_far_test(p);
  89        iounmap(p);
  90}
  91
  92static int __init init(void)
  93{
  94        unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
  95
  96        if (mmio_address == 0) {
  97                pr_err(MODULE_NAME ": you have to use the module argument "
  98                                                        "mmio_address.\n");
  99                pr_err(MODULE_NAME ": DO NOT LOAD THIS MODULE UNLESS"
 100                                " YOU REALLY KNOW WHAT YOU ARE DOING!\n");
 101                return -ENXIO;
 102        }
 103
 104        pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI "
 105                "address space, and writing 16 kB of rubbish in there.\n",
 106                 size >> 10, mmio_address);
 107        do_test(size);
 108        pr_info(MODULE_NAME ": All done.\n");
 109        return 0;
 110}
 111
 112static void __exit cleanup(void)
 113{
 114        pr_debug(MODULE_NAME ": unloaded.\n");
 115}
 116
 117module_init(init);
 118module_exit(cleanup);
 119MODULE_LICENSE("GPL");
 120