#define pr_fmt(fmt) …
#include <linux/sched/task_stack.h>
#include <linux/scatterlist.h>
#include <linux/dma-map-ops.h>
#include <linux/sched/task.h>
#include <linux/stacktrace.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/export.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/ctype.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <asm/sections.h>
#include "debug.h"
#define HASH_SIZE …
#define HASH_FN_SHIFT …
#define HASH_FN_MASK …
#define PREALLOC_DMA_DEBUG_ENTRIES …
#define DMA_DEBUG_DYNAMIC_ENTRIES …
enum { … };
enum map_err_types { … };
#define DMA_DEBUG_STACKTRACE_ENTRIES …
struct dma_debug_entry { … } ____cacheline_aligned_in_smp;
match_fn;
struct hash_bucket { … };
static struct hash_bucket dma_entry_hash[HASH_SIZE];
static LIST_HEAD(free_entries);
static DEFINE_SPINLOCK(free_entries_lock);
static bool global_disable __read_mostly;
static bool dma_debug_initialized __read_mostly;
static inline bool dma_debug_disabled(void)
{ … }
static u32 error_count;
static u32 show_all_errors __read_mostly;
static u32 show_num_errors = …;
static u32 num_free_entries;
static u32 min_free_entries;
static u32 nr_total_entries;
static u32 nr_prealloc_entries = …;
#define NAME_MAX_LEN …
static char current_driver_name[NAME_MAX_LEN] __read_mostly;
static struct device_driver *current_driver __read_mostly;
static DEFINE_RWLOCK(driver_name_lock);
static const char *const maperr2str[] = …;
static const char *type2name[] = …;
static const char *dir2name[] = …;
static inline void dump_entry_trace(struct dma_debug_entry *entry)
{ … }
static bool driver_filter(struct device *dev)
{ … }
#define err_printk(dev, entry, format, arg...) …
static int hash_fn(struct dma_debug_entry *entry)
{ … }
static struct hash_bucket *get_hash_bucket(struct dma_debug_entry *entry,
unsigned long *flags)
__acquires(&dma_entry_hash[idx].lock)
{ … }
static void put_hash_bucket(struct hash_bucket *bucket,
unsigned long flags)
__releases(&bucket->lock)
{ … }
static bool exact_match(struct dma_debug_entry *a, struct dma_debug_entry *b)
{ … }
static bool containing_match(struct dma_debug_entry *a,
struct dma_debug_entry *b)
{ … }
static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket,
struct dma_debug_entry *ref,
match_fn match)
{ … }
static struct dma_debug_entry *bucket_find_exact(struct hash_bucket *bucket,
struct dma_debug_entry *ref)
{ … }
static struct dma_debug_entry *bucket_find_contain(struct hash_bucket **bucket,
struct dma_debug_entry *ref,
unsigned long *flags)
{ … }
static void hash_bucket_add(struct hash_bucket *bucket,
struct dma_debug_entry *entry)
{ … }
static void hash_bucket_del(struct dma_debug_entry *entry)
{ … }
static unsigned long long phys_addr(struct dma_debug_entry *entry)
{ … }
static RADIX_TREE(dma_active_cacheline, GFP_ATOMIC);
static DEFINE_SPINLOCK(radix_lock);
#define ACTIVE_CACHELINE_MAX_OVERLAP …
#define CACHELINE_PER_PAGE_SHIFT …
#define CACHELINES_PER_PAGE …
static phys_addr_t to_cacheline_number(struct dma_debug_entry *entry)
{ … }
static int active_cacheline_read_overlap(phys_addr_t cln)
{ … }
static int active_cacheline_set_overlap(phys_addr_t cln, int overlap)
{ … }
static void active_cacheline_inc_overlap(phys_addr_t cln)
{ … }
static int active_cacheline_dec_overlap(phys_addr_t cln)
{ … }
static int active_cacheline_insert(struct dma_debug_entry *entry)
{ … }
static void active_cacheline_remove(struct dma_debug_entry *entry)
{ … }
void debug_dma_dump_mappings(struct device *dev)
{ … }
static int dump_show(struct seq_file *seq, void *v)
{ … }
DEFINE_SHOW_ATTRIBUTE(…);
static void add_dma_entry(struct dma_debug_entry *entry, unsigned long attrs)
{ … }
static int dma_debug_create_entries(gfp_t gfp)
{ … }
static struct dma_debug_entry *__dma_entry_alloc(void)
{ … }
static void __dma_entry_alloc_check_leak(u32 nr_entries)
{ … }
static struct dma_debug_entry *dma_entry_alloc(void)
{ … }
static void dma_entry_free(struct dma_debug_entry *entry)
{ … }
static ssize_t filter_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{ … }
static ssize_t filter_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{ … }
static const struct file_operations filter_fops = …;
static int __init dma_debug_fs_init(void)
{ … }
core_initcall_sync(dma_debug_fs_init);
static int device_dma_allocations(struct device *dev, struct dma_debug_entry **out_entry)
{ … }
static int dma_debug_device_change(struct notifier_block *nb, unsigned long action, void *data)
{ … }
void dma_debug_add_bus(const struct bus_type *bus)
{ … }
static int dma_debug_init(void)
{ … }
core_initcall(dma_debug_init);
static __init int dma_debug_cmdline(char *str)
{ … }
static __init int dma_debug_entries_cmdline(char *str)
{ … }
__setup(…);
__setup(…);
static void check_unmap(struct dma_debug_entry *ref)
{ … }
static void check_for_stack(struct device *dev,
struct page *page, size_t offset)
{ … }
static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len)
{ … }
static void check_sync(struct device *dev,
struct dma_debug_entry *ref,
bool to_cpu)
{ … }
static void check_sg_segment(struct device *dev, struct scatterlist *sg)
{ … }
void debug_dma_map_single(struct device *dev, const void *addr,
unsigned long len)
{ … }
EXPORT_SYMBOL(…);
void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
size_t size, int direction, dma_addr_t dma_addr,
unsigned long attrs)
{ … }
void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{ … }
EXPORT_SYMBOL(…);
void debug_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, int direction)
{ … }
void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, int mapped_ents, int direction,
unsigned long attrs)
{ … }
static int get_nr_mapped_entries(struct device *dev,
struct dma_debug_entry *ref)
{ … }
void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, int dir)
{ … }
void debug_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t dma_addr, void *virt,
unsigned long attrs)
{ … }
void debug_dma_free_coherent(struct device *dev, size_t size,
void *virt, dma_addr_t dma_addr)
{ … }
void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
int direction, dma_addr_t dma_addr,
unsigned long attrs)
{ … }
void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
size_t size, int direction)
{ … }
void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
size_t size, int direction)
{ … }
void debug_dma_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size,
int direction)
{ … }
void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
int nelems, int direction)
{ … }
void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
int nelems, int direction)
{ … }
static int __init dma_debug_driver_setup(char *str)
{ … }
__setup(…);