When the code disables itself at runtime this is most likely because it ran
out of dma_debug_entries and was unable to allocate more on-demand. 65536
entries are preallocated at boot - if this is too low for you boot with
-'dma_debug_entries=<your_desired_number>' to overwrite the default. The
+'dma_debug_entries=<your_desired_number>' to overwrite the default. Note
+that the code allocates entries in batches, so the exact number of
+preallocated entries may be greater than the actual number requested. The
code will print to the kernel log each time it has dynamically allocated
as many entries as were initially preallocated. This is to indicate that a
larger preallocation size may be appropriate, or if it happens continually
#define HASH_FN_SHIFT 13
#define HASH_FN_MASK (HASH_SIZE - 1)
-/* allow architectures to override this if absolutely required */
-#ifndef PREALLOC_DMA_DEBUG_ENTRIES
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
-#endif
/* If the pool runs out, add this many new entries at once */
-#define DMA_DEBUG_DYNAMIC_ENTRIES 256
+#define DMA_DEBUG_DYNAMIC_ENTRIES (PAGE_SIZE / sizeof(struct dma_debug_entry))
enum {
dma_debug_single,
*/
}
-static int dma_debug_create_entries(u32 num_entries, gfp_t gfp)
+static int dma_debug_create_entries(gfp_t gfp)
{
- struct dma_debug_entry *entry, *next_entry;
+ struct dma_debug_entry *entry;
int i;
- for (i = 0; i < num_entries; ++i) {
- entry = kzalloc(sizeof(*entry), gfp);
- if (!entry)
- goto out_err;
+ entry = (void *)get_zeroed_page(gfp);
+ if (!entry)
+ return -ENOMEM;
- list_add_tail(&entry->list, &free_entries);
- }
+ for (i = 0; i < DMA_DEBUG_DYNAMIC_ENTRIES; i++)
+ list_add_tail(&entry[i].list, &free_entries);
- num_free_entries += num_entries;
- nr_total_entries += num_entries;
+ num_free_entries += DMA_DEBUG_DYNAMIC_ENTRIES;
+ nr_total_entries += DMA_DEBUG_DYNAMIC_ENTRIES;
return 0;
-
-out_err:
-
- list_for_each_entry_safe(entry, next_entry, &free_entries, list) {
- list_del(&entry->list);
- kfree(entry);
- }
-
- return -ENOMEM;
}
static struct dma_debug_entry *__dma_entry_alloc(void)
spin_lock_irqsave(&free_entries_lock, flags);
if (num_free_entries == 0) {
- if (dma_debug_create_entries(DMA_DEBUG_DYNAMIC_ENTRIES,
- GFP_ATOMIC)) {
+ if (dma_debug_create_entries(GFP_ATOMIC)) {
global_disable = true;
spin_unlock_irqrestore(&free_entries_lock, flags);
pr_err("debugging out of memory - disabling\n");
static int dma_debug_init(void)
{
- int i;
+ int i, nr_pages;
/* Do not use dma_debug_initialized here, since we really want to be
* called to set dma_debug_initialized
return 0;
}
- if (dma_debug_create_entries(nr_prealloc_entries, GFP_KERNEL) != 0) {
+ nr_pages = DIV_ROUND_UP(nr_prealloc_entries, DMA_DEBUG_DYNAMIC_ENTRIES);
+ for (i = 0; i < nr_pages; ++i)
+ dma_debug_create_entries(GFP_KERNEL);
+ if (num_free_entries >= nr_prealloc_entries) {
+ pr_info("preallocated %d debug entries\n", nr_total_entries);
+ } else if (num_free_entries > 0) {
+ pr_warn("%d debug entries requested but only %d allocated\n",
+ nr_prealloc_entries, nr_total_entries);
+ } else {
pr_err("debugging out of memory error - disabled\n");
global_disable = true;
return 0;
}
-
min_free_entries = num_free_entries;
- pr_info("preallocated %d debug entries\n", nr_total_entries);
dma_debug_initialized = true;