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