aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-06-07 05:36:02 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-07 05:36:02 -0400
commit62a6f465f6572e1f28765c583c12753bb3e23715 (patch)
tree35ccf596b4abbeec9e1244f31e5b4e5d079899f5
parent56fdd18c7b89a2fac1dfe5d54750c9143867fdc4 (diff)
parentbdc2911cde7d18580a545483844d75fdb3551729 (diff)
Merge branch 'dma-debug/2.6.31' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu into core/iommu
-rw-r--r--Documentation/DMA-API.txt12
-rw-r--r--Documentation/kernel-parameters.txt7
-rw-r--r--lib/dma-debug.c291
3 files changed, 288 insertions, 22 deletions
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index d9aa43d78bcc..25fb8bcf32a2 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -704,12 +704,24 @@ this directory the following files can currently be found:
704 The current number of free dma_debug_entries 704 The current number of free dma_debug_entries
705 in the allocator. 705 in the allocator.
706 706
707 dma-api/driver-filter
708 You can write a name of a driver into this file
709 to limit the debug output to requests from that
710 particular driver. Write an empty string to
711 that file to disable the filter and see
712 all errors again.
713
707If you have this code compiled into your kernel it will be enabled by default. 714If you have this code compiled into your kernel it will be enabled by default.
708If you want to boot without the bookkeeping anyway you can provide 715If you want to boot without the bookkeeping anyway you can provide
709'dma_debug=off' as a boot parameter. This will disable DMA-API debugging. 716'dma_debug=off' as a boot parameter. This will disable DMA-API debugging.
710Notice that you can not enable it again at runtime. You have to reboot to do 717Notice that you can not enable it again at runtime. You have to reboot to do
711so. 718so.
712 719
720If you want to see debug messages only for a special device driver you can
721specify the dma_debug_driver=<drivername> parameter. This will enable the
722driver filter at boot time. The debug code will only print errors for that
723driver afterwards. This filter can be disabled or changed later using debugfs.
724
713When the code disables itself at runtime this is most likely because it ran 725When the code disables itself at runtime this is most likely because it ran
714out of dma_debug_entries. These entries are preallocated at boot. The number 726out of dma_debug_entries. These entries are preallocated at boot. The number
715of preallocated entries is defined per architecture. If it is too low for you 727of preallocated entries is defined per architecture. If it is too low for you
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e2999cb4745a..8f9e17c855a0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -641,6 +641,13 @@ and is between 256 and 4096 characters. It is defined in the file
641 DMA-API debugging code disables itself because the 641 DMA-API debugging code disables itself because the
642 architectural default is too low. 642 architectural default is too low.
643 643
644 dma_debug_driver=<driver_name>
645 With this option the DMA-API debugging driver
646 filter feature can be enabled at boot time. Just
647 pass the driver to filter for as the parameter.
648 The filter can be disabled or changed to another
649 driver later using sysfs.
650
644 dscc4.setup= [NET] 651 dscc4.setup= [NET]
645 652
646 dtc3181e= [HW,SCSI] 653 dtc3181e= [HW,SCSI]
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 8fcc09c91e1b..77053d9ef513 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -23,9 +23,11 @@
23#include <linux/dma-debug.h> 23#include <linux/dma-debug.h>
24#include <linux/spinlock.h> 24#include <linux/spinlock.h>
25#include <linux/debugfs.h> 25#include <linux/debugfs.h>
26#include <linux/uaccess.h>
26#include <linux/device.h> 27#include <linux/device.h>
27#include <linux/types.h> 28#include <linux/types.h>
28#include <linux/sched.h> 29#include <linux/sched.h>
30#include <linux/ctype.h>
29#include <linux/list.h> 31#include <linux/list.h>
30#include <linux/slab.h> 32#include <linux/slab.h>
31 33
@@ -98,6 +100,16 @@ static struct dentry *show_all_errors_dent __read_mostly;
98static struct dentry *show_num_errors_dent __read_mostly; 100static struct dentry *show_num_errors_dent __read_mostly;
99static struct dentry *num_free_entries_dent __read_mostly; 101static struct dentry *num_free_entries_dent __read_mostly;
100static struct dentry *min_free_entries_dent __read_mostly; 102static struct dentry *min_free_entries_dent __read_mostly;
103static struct dentry *filter_dent __read_mostly;
104
105/* per-driver filter related state */
106
107#define NAME_MAX_LEN 64
108
109static char current_driver_name[NAME_MAX_LEN] __read_mostly;
110static struct device_driver *current_driver __read_mostly;
111
112static DEFINE_RWLOCK(driver_name_lock);
101 113
102static const char *type2name[4] = { "single", "page", 114static const char *type2name[4] = { "single", "page",
103 "scather-gather", "coherent" }; 115 "scather-gather", "coherent" };
@@ -105,6 +117,11 @@ static const char *type2name[4] = { "single", "page",
105static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE", 117static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
106 "DMA_FROM_DEVICE", "DMA_NONE" }; 118 "DMA_FROM_DEVICE", "DMA_NONE" };
107 119
120/* little merge helper - remove it after the merge window */
121#ifndef BUS_NOTIFY_UNBOUND_DRIVER
122#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005
123#endif
124
108/* 125/*
109 * The access to some variables in this macro is racy. We can't use atomic_t 126 * The access to some variables in this macro is racy. We can't use atomic_t
110 * here because all these variables are exported to debugfs. Some of them even 127 * here because all these variables are exported to debugfs. Some of them even
@@ -128,9 +145,48 @@ static inline void dump_entry_trace(struct dma_debug_entry *entry)
128#endif 145#endif
129} 146}
130 147
148static bool driver_filter(struct device *dev)
149{
150 /* driver filter off */
151 if (likely(!current_driver_name[0]))
152 return true;
153
154 /* driver filter on and initialized */
155 if (current_driver && dev->driver == current_driver)
156 return true;
157
158 /* driver filter on but not yet initialized */
159 if (!current_driver && current_driver_name[0]) {
160 struct device_driver *drv = get_driver(dev->driver);
161 unsigned long flags;
162 bool ret = false;
163
164 if (!drv)
165 return false;
166
167 /* lock to protect against change of current_driver_name */
168 read_lock_irqsave(&driver_name_lock, flags);
169
170 if (drv->name &&
171 strncmp(current_driver_name, drv->name,
172 NAME_MAX_LEN-1) == 0) {
173 current_driver = drv;
174 ret = true;
175 }
176
177 read_unlock_irqrestore(&driver_name_lock, flags);
178 put_driver(drv);
179
180 return ret;
181 }
182
183 return false;
184}
185
131#define err_printk(dev, entry, format, arg...) do { \ 186#define err_printk(dev, entry, format, arg...) do { \
132 error_count += 1; \ 187 error_count += 1; \
133 if (show_all_errors || show_num_errors > 0) { \ 188 if (driver_filter(dev) && \
189 (show_all_errors || show_num_errors > 0)) { \
134 WARN(1, "%s %s: " format, \ 190 WARN(1, "%s %s: " format, \
135 dev_driver_string(dev), \ 191 dev_driver_string(dev), \
136 dev_name(dev) , ## arg); \ 192 dev_name(dev) , ## arg); \
@@ -442,6 +498,97 @@ out_err:
442 return -ENOMEM; 498 return -ENOMEM;
443} 499}
444 500
501static ssize_t filter_read(struct file *file, char __user *user_buf,
502 size_t count, loff_t *ppos)
503{
504 unsigned long flags;
505 char buf[NAME_MAX_LEN + 1];
506 int len;
507
508 if (!current_driver_name[0])
509 return 0;
510
511 /*
512 * We can't copy to userspace directly because current_driver_name can
513 * only be read under the driver_name_lock with irqs disabled. So
514 * create a temporary copy first.
515 */
516 read_lock_irqsave(&driver_name_lock, flags);
517 len = scnprintf(buf, NAME_MAX_LEN + 1, "%s\n", current_driver_name);
518 read_unlock_irqrestore(&driver_name_lock, flags);
519
520 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
521}
522
523static ssize_t filter_write(struct file *file, const char __user *userbuf,
524 size_t count, loff_t *ppos)
525{
526 unsigned long flags;
527 char buf[NAME_MAX_LEN];
528 size_t len = NAME_MAX_LEN - 1;
529 int i;
530
531 /*
532 * We can't copy from userspace directly. Access to
533 * current_driver_name is protected with a write_lock with irqs
534 * disabled. Since copy_from_user can fault and may sleep we
535 * need to copy to temporary buffer first
536 */
537 len = min(count, len);
538 if (copy_from_user(buf, userbuf, len))
539 return -EFAULT;
540
541 buf[len] = 0;
542
543 write_lock_irqsave(&driver_name_lock, flags);
544
545 /* Now handle the string we got from userspace very carefully.
546 * The rules are:
547 * - only use the first token we got
548 * - token delimiter is everything looking like a space
549 * character (' ', '\n', '\t' ...)
550 *
551 */
552 if (!isalnum(buf[0])) {
553 /*
554 If the first character userspace gave us is not
555 * alphanumerical then assume the filter should be
556 * switched off.
557 */
558 if (current_driver_name[0])
559 printk(KERN_INFO "DMA-API: switching off dma-debug "
560 "driver filter\n");
561 current_driver_name[0] = 0;
562 current_driver = NULL;
563 goto out_unlock;
564 }
565
566 /*
567 * Now parse out the first token and use it as the name for the
568 * driver to filter for.
569 */
570 for (i = 0; i < NAME_MAX_LEN; ++i) {
571 current_driver_name[i] = buf[i];
572 if (isspace(buf[i]) || buf[i] == ' ' || buf[i] == 0)
573 break;
574 }
575 current_driver_name[i] = 0;
576 current_driver = NULL;
577
578 printk(KERN_INFO "DMA-API: enable driver filter for driver [%s]\n",
579 current_driver_name);
580
581out_unlock:
582 write_unlock_irqrestore(&driver_name_lock, flags);
583
584 return count;
585}
586
587const struct file_operations filter_fops = {
588 .read = filter_read,
589 .write = filter_write,
590};
591
445static int dma_debug_fs_init(void) 592static int dma_debug_fs_init(void)
446{ 593{
447 dma_debug_dent = debugfs_create_dir("dma-api", NULL); 594 dma_debug_dent = debugfs_create_dir("dma-api", NULL);
@@ -485,6 +632,11 @@ static int dma_debug_fs_init(void)
485 if (!min_free_entries_dent) 632 if (!min_free_entries_dent)
486 goto out_err; 633 goto out_err;
487 634
635 filter_dent = debugfs_create_file("driver_filter", 0644,
636 dma_debug_dent, NULL, &filter_fops);
637 if (!filter_dent)
638 goto out_err;
639
488 return 0; 640 return 0;
489 641
490out_err: 642out_err:
@@ -493,9 +645,60 @@ out_err:
493 return -ENOMEM; 645 return -ENOMEM;
494} 646}
495 647
648static int device_dma_allocations(struct device *dev)
649{
650 struct dma_debug_entry *entry;
651 unsigned long flags;
652 int count = 0, i;
653
654 for (i = 0; i < HASH_SIZE; ++i) {
655 spin_lock_irqsave(&dma_entry_hash[i].lock, flags);
656 list_for_each_entry(entry, &dma_entry_hash[i].list, list) {
657 if (entry->dev == dev)
658 count += 1;
659 }
660 spin_unlock_irqrestore(&dma_entry_hash[i].lock, flags);
661 }
662
663 return count;
664}
665
666static int dma_debug_device_change(struct notifier_block *nb,
667 unsigned long action, void *data)
668{
669 struct device *dev = data;
670 int count;
671
672
673 switch (action) {
674 case BUS_NOTIFY_UNBOUND_DRIVER:
675 count = device_dma_allocations(dev);
676 if (count == 0)
677 break;
678 err_printk(dev, NULL, "DMA-API: device driver has pending "
679 "DMA allocations while released from device "
680 "[count=%d]\n", count);
681 break;
682 default:
683 break;
684 }
685
686 return 0;
687}
688
496void dma_debug_add_bus(struct bus_type *bus) 689void dma_debug_add_bus(struct bus_type *bus)
497{ 690{
498 /* FIXME: register notifier */ 691 struct notifier_block *nb;
692
693 nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
694 if (nb == NULL) {
695 printk(KERN_ERR "dma_debug_add_bus: out of memory\n");
696 return;
697 }
698
699 nb->notifier_call = dma_debug_device_change;
700
701 bus_register_notifier(bus, nb);
499} 702}
500 703
501/* 704/*
@@ -818,15 +1021,15 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
818 entry->type = dma_debug_sg; 1021 entry->type = dma_debug_sg;
819 entry->dev = dev; 1022 entry->dev = dev;
820 entry->paddr = sg_phys(s); 1023 entry->paddr = sg_phys(s);
821 entry->size = s->length; 1024 entry->size = sg_dma_len(s);
822 entry->dev_addr = s->dma_address; 1025 entry->dev_addr = sg_dma_address(s);
823 entry->direction = direction; 1026 entry->direction = direction;
824 entry->sg_call_ents = nents; 1027 entry->sg_call_ents = nents;
825 entry->sg_mapped_ents = mapped_ents; 1028 entry->sg_mapped_ents = mapped_ents;
826 1029
827 if (!PageHighMem(sg_page(s))) { 1030 if (!PageHighMem(sg_page(s))) {
828 check_for_stack(dev, sg_virt(s)); 1031 check_for_stack(dev, sg_virt(s));
829 check_for_illegal_area(dev, sg_virt(s), s->length); 1032 check_for_illegal_area(dev, sg_virt(s), sg_dma_len(s));
830 } 1033 }
831 1034
832 add_dma_entry(entry); 1035 add_dma_entry(entry);
@@ -834,13 +1037,32 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
834} 1037}
835EXPORT_SYMBOL(debug_dma_map_sg); 1038EXPORT_SYMBOL(debug_dma_map_sg);
836 1039
1040static int get_nr_mapped_entries(struct device *dev, struct scatterlist *s)
1041{
1042 struct dma_debug_entry *entry;
1043 struct hash_bucket *bucket;
1044 unsigned long flags;
1045 int mapped_ents = 0;
1046 struct dma_debug_entry ref;
1047
1048 ref.dev = dev;
1049 ref.dev_addr = sg_dma_address(s);
1050 ref.size = sg_dma_len(s),
1051
1052 bucket = get_hash_bucket(&ref, &flags);
1053 entry = hash_bucket_find(bucket, &ref);
1054 if (entry)
1055 mapped_ents = entry->sg_mapped_ents;
1056 put_hash_bucket(bucket, &flags);
1057
1058 return mapped_ents;
1059}
1060
837void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, 1061void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
838 int nelems, int dir) 1062 int nelems, int dir)
839{ 1063{
840 struct dma_debug_entry *entry;
841 struct scatterlist *s; 1064 struct scatterlist *s;
842 int mapped_ents = 0, i; 1065 int mapped_ents = 0, i;
843 unsigned long flags;
844 1066
845 if (unlikely(global_disable)) 1067 if (unlikely(global_disable))
846 return; 1068 return;
@@ -851,8 +1073,8 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
851 .type = dma_debug_sg, 1073 .type = dma_debug_sg,
852 .dev = dev, 1074 .dev = dev,
853 .paddr = sg_phys(s), 1075 .paddr = sg_phys(s),
854 .dev_addr = s->dma_address, 1076 .dev_addr = sg_dma_address(s),
855 .size = s->length, 1077 .size = sg_dma_len(s),
856 .direction = dir, 1078 .direction = dir,
857 .sg_call_ents = 0, 1079 .sg_call_ents = 0,
858 }; 1080 };
@@ -860,14 +1082,9 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
860 if (mapped_ents && i >= mapped_ents) 1082 if (mapped_ents && i >= mapped_ents)
861 break; 1083 break;
862 1084
863 if (mapped_ents == 0) { 1085 if (!i) {
864 struct hash_bucket *bucket;
865 ref.sg_call_ents = nelems; 1086 ref.sg_call_ents = nelems;
866 bucket = get_hash_bucket(&ref, &flags); 1087 mapped_ents = get_nr_mapped_entries(dev, s);
867 entry = hash_bucket_find(bucket, &ref);
868 if (entry)
869 mapped_ents = entry->sg_mapped_ents;
870 put_hash_bucket(bucket, &flags);
871 } 1088 }
872 1089
873 check_unmap(&ref); 1090 check_unmap(&ref);
@@ -969,14 +1186,20 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
969 int nelems, int direction) 1186 int nelems, int direction)
970{ 1187{
971 struct scatterlist *s; 1188 struct scatterlist *s;
972 int i; 1189 int mapped_ents = 0, i;
973 1190
974 if (unlikely(global_disable)) 1191 if (unlikely(global_disable))
975 return; 1192 return;
976 1193
977 for_each_sg(sg, s, nelems, i) { 1194 for_each_sg(sg, s, nelems, i) {
978 check_sync(dev, s->dma_address, s->dma_length, 0, 1195 if (!i)
979 direction, true); 1196 mapped_ents = get_nr_mapped_entries(dev, s);
1197
1198 if (i >= mapped_ents)
1199 break;
1200
1201 check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0,
1202 direction, true);
980 } 1203 }
981} 1204}
982EXPORT_SYMBOL(debug_dma_sync_sg_for_cpu); 1205EXPORT_SYMBOL(debug_dma_sync_sg_for_cpu);
@@ -985,15 +1208,39 @@ void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
985 int nelems, int direction) 1208 int nelems, int direction)
986{ 1209{
987 struct scatterlist *s; 1210 struct scatterlist *s;
988 int i; 1211 int mapped_ents = 0, i;
989 1212
990 if (unlikely(global_disable)) 1213 if (unlikely(global_disable))
991 return; 1214 return;
992 1215
993 for_each_sg(sg, s, nelems, i) { 1216 for_each_sg(sg, s, nelems, i) {
994 check_sync(dev, s->dma_address, s->dma_length, 0, 1217 if (!i)
995 direction, false); 1218 mapped_ents = get_nr_mapped_entries(dev, s);
1219
1220 if (i >= mapped_ents)
1221 break;
1222
1223 check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0,
1224 direction, false);
996 } 1225 }
997} 1226}
998EXPORT_SYMBOL(debug_dma_sync_sg_for_device); 1227EXPORT_SYMBOL(debug_dma_sync_sg_for_device);
999 1228
1229static int __init dma_debug_driver_setup(char *str)
1230{
1231 int i;
1232
1233 for (i = 0; i < NAME_MAX_LEN - 1; ++i, ++str) {
1234 current_driver_name[i] = *str;
1235 if (*str == 0)
1236 break;
1237 }
1238
1239 if (current_driver_name[0])
1240 printk(KERN_INFO "DMA-API: enable driver filter for "
1241 "driver [%s]\n", current_driver_name);
1242
1243
1244 return 1;
1245}
1246__setup("dma_debug_driver=", dma_debug_driver_setup);