diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 0ca54421ce977b7f82055644a08d8ea0ae3ca406..26cbb12df79eaabd32789a029e280d93bfe8108e 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -32,6 +32,7 @@ #include <linux/swap.h> #include <linux/mm_types.h> #include <linux/dma-contiguous.h> +#include <trace/events/kmem.h> struct cma { unsigned long base_pfn; @@ -310,6 +311,7 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count, struct cma *cma = dev_get_cma_area(dev); struct page *page = NULL; int ret; + int tries = 0; if (!cma || !cma->count) return NULL; @@ -342,6 +344,9 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count, } else if (ret != -EBUSY) { break; } + tries++; + trace_dma_alloc_contiguous_retry(tries); + pr_debug("%s(): memory range at %p is busy, retrying\n", __func__, pfn_to_page(pfn)); /* try again with a bit different memory target */ diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index 593063af995754726c79b403d82b40bc0549173c..6b7c44c333fbcc4df92c5c260dab7848a73f99e0 100644 --- a/drivers/gpu/ion/ion.c +++ b/drivers/gpu/ion/ion.c @@ -2,7 +2,7 @@ * drivers/gpu/ion/ion.c * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -35,6 +35,8 @@ #include <linux/debugfs.h> #include <linux/dma-buf.h> #include <linux/msm_ion.h> +#include <trace/events/kmem.h> + #include <mach/iommu_domains.h> #include "ion_priv.h" @@ -452,9 +454,16 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, if (secure_allocation && (heap->type != (enum ion_heap_type) ION_HEAP_TYPE_CP)) continue; + trace_ion_alloc_buffer_start(client->name, heap->name, len, + heap_mask, flags); buffer = ion_buffer_create(heap, dev, len, align, flags); + trace_ion_alloc_buffer_end(client->name, heap->name, len, + heap_mask, flags); if (!IS_ERR_OR_NULL(buffer)) break; + + trace_ion_alloc_buffer_fallback(client->name, heap->name, len, + heap_mask, flags, PTR_ERR(buffer)); if (dbg_str_idx < MAX_DBG_STR_LEN) { unsigned int len_left = MAX_DBG_STR_LEN-dbg_str_idx-1; int ret_value = snprintf(&dbg_str[dbg_str_idx], @@ -473,10 +482,15 @@ struct ion_handle *ion_alloc(struct ion_client *client, size_t len, } mutex_unlock(&dev->lock); - if (buffer == NULL) + if (buffer == NULL) { + trace_ion_alloc_buffer_fail(client->name, dbg_str, len, + heap_mask, flags, -ENODEV); return ERR_PTR(-ENODEV); + } if (IS_ERR(buffer)) { + trace_ion_alloc_buffer_fail(client->name, dbg_str, len, + heap_mask, flags, PTR_ERR(buffer)); pr_debug("ION is unable to allocate 0x%x bytes (alignment: " "0x%x) from heap(s) %sfor client %s with heap " "mask 0x%x\n", diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c index d6e26ff6d9c52b3cc30d96a25bf54f1d8c5f807e..981858cf9f9ca499778bdc00476a60b09a52f87b 100644 --- a/drivers/gpu/ion/ion_cp_heap.c +++ b/drivers/gpu/ion/ion_cp_heap.c @@ -29,6 +29,7 @@ #include <linux/fmem.h> #include <linux/iommu.h> #include <linux/dma-mapping.h> +#include <trace/events/kmem.h> #include <asm/mach/map.h> @@ -162,8 +163,10 @@ static int allocate_heap_memory(struct ion_heap *heap) &(cp_heap->handle), 0, &attrs); - if (!cp_heap->cpu_addr) + if (!cp_heap->cpu_addr) { + trace_ion_cp_alloc_retry(tries); msleep(20); + } } if (!cp_heap->cpu_addr) diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h index 6bc943ecb84135034ee968772726efb8383cb1c8..00121353d9577654797ea2c9d60c264f8a392f93 100644 --- a/include/trace/events/kmem.h +++ b/include/trace/events/kmem.h @@ -302,6 +302,199 @@ TRACE_EVENT(mm_page_alloc_extfrag, __entry->alloc_migratetype == __entry->fallback_migratetype) ); + +DECLARE_EVENT_CLASS(ion_alloc, + + TP_PROTO(const char *client_name, + const char *heap_name, + size_t len, + unsigned int mask, + unsigned int flags), + + TP_ARGS(client_name, heap_name, len, mask, flags), + + TP_STRUCT__entry( + __field(const char *, client_name) + __field(const char *, heap_name) + __field(size_t, len) + __field(unsigned int, mask) + __field(unsigned int, flags) + ), + + TP_fast_assign( + __entry->client_name = client_name; + __entry->heap_name = heap_name; + __entry->len = len; + __entry->mask = mask; + __entry->flags = flags; + ), + + TP_printk("client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x", + __entry->client_name, + __entry->heap_name, + __entry->len, + __entry->mask, + __entry->flags) +); + +DEFINE_EVENT(ion_alloc, ion_alloc_buffer_start, + + TP_PROTO(const char *client_name, + const char *heap_name, + size_t len, + unsigned int mask, + unsigned int flags), + + TP_ARGS(client_name, heap_name, len, mask, flags) +); + +DEFINE_EVENT(ion_alloc, ion_alloc_buffer_end, + + TP_PROTO(const char *client_name, + const char *heap_name, + size_t len, + unsigned int mask, + unsigned int flags), + + TP_ARGS(client_name, heap_name, len, mask, flags) +); + +DECLARE_EVENT_CLASS(ion_alloc_error, + + TP_PROTO(const char *client_name, + const char *heap_name, + size_t len, + unsigned int mask, + unsigned int flags, + long error), + + TP_ARGS(client_name, heap_name, len, mask, flags, error), + + TP_STRUCT__entry( + __field(const char *, client_name) + __field(const char *, heap_name) + __field(size_t, len) + __field(unsigned int, mask) + __field(unsigned int, flags) + __field(long, error) + ), + + TP_fast_assign( + __entry->client_name = client_name; + __entry->heap_name = heap_name; + __entry->len = len; + __entry->mask = mask; + __entry->flags = flags; + __entry->error = error; + ), + + TP_printk( + "client_name=%s heap_name=%s len=%zu mask=0x%x flags=0x%x error=%ld", + __entry->client_name, + __entry->heap_name, + __entry->len, + __entry->mask, + __entry->flags, + __entry->error) +); + + +DEFINE_EVENT(ion_alloc_error, ion_alloc_buffer_fallback, + + TP_PROTO(const char *client_name, + const char *heap_name, + size_t len, + unsigned int mask, + unsigned int flags, + long error), + + TP_ARGS(client_name, heap_name, len, mask, flags, error) +); + +DEFINE_EVENT(ion_alloc_error, ion_alloc_buffer_fail, + + TP_PROTO(const char *client_name, + const char *heap_name, + size_t len, + unsigned int mask, + unsigned int flags, + long error), + + TP_ARGS(client_name, heap_name, len, mask, flags, error) +); + + +DECLARE_EVENT_CLASS(alloc_retry, + + TP_PROTO(int tries), + + TP_ARGS(tries), + + TP_STRUCT__entry( + __field(int, tries) + ), + + TP_fast_assign( + __entry->tries = tries; + ), + + TP_printk("tries=%d", + __entry->tries) +); + +DEFINE_EVENT(alloc_retry, ion_cp_alloc_retry, + + TP_PROTO(int tries), + + TP_ARGS(tries) +); + +DEFINE_EVENT(alloc_retry, migrate_retry, + + TP_PROTO(int tries), + + TP_ARGS(tries) +); + +DEFINE_EVENT(alloc_retry, dma_alloc_contiguous_retry, + + TP_PROTO(int tries), + + TP_ARGS(tries) +); + +DECLARE_EVENT_CLASS(migrate_pages, + + TP_PROTO(int mode), + + TP_ARGS(mode), + + TP_STRUCT__entry( + __field(int, mode) + ), + + TP_fast_assign( + __entry->mode = mode; + ), + + TP_printk("mode=%d", + __entry->mode) +); + +DEFINE_EVENT(migrate_pages, migrate_pages_start, + + TP_PROTO(int mode), + + TP_ARGS(mode) +); + +DEFINE_EVENT(migrate_pages, migrate_pages_end, + + TP_PROTO(int mode), + + TP_ARGS(mode) +); + #endif /* _TRACE_KMEM_H */ /* This part must be outside protection */ diff --git a/mm/migrate.c b/mm/migrate.c index 6f0c24438bbaaf6ffdaa4f840ab8da37cf9e236a..9a16783dfdd52567e0974bb2ea6c2635ab200442 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -36,6 +36,7 @@ #include <linux/hugetlb_cgroup.h> #include <linux/gfp.h> #include <linux/balloon_compaction.h> +#include <trace/events/kmem.h> #include <asm/tlbflush.h> @@ -1016,6 +1017,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, int swapwrite = current->flags & PF_SWAPWRITE; int rc; + trace_migrate_pages_start(mode); if (!swapwrite) current->flags |= PF_SWAPWRITE; @@ -1033,6 +1035,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, goto out; case -EAGAIN: retry++; + trace_migrate_retry(retry); break; case MIGRATEPAGE_SUCCESS: nr_succeeded++; @@ -1055,6 +1058,7 @@ out: if (!swapwrite) current->flags &= ~PF_SWAPWRITE; + trace_migrate_pages_end(mode); return rc; }