diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-08-25 06:15:50 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-09-22 20:05:21 -0400 |
commit | 1c5d22f76dc721f3acb7a3dadc657a221e487fb7 (patch) | |
tree | 99a69f1be4f10d1e38af2c5ece4b5905f7a5701a | |
parent | 74dff282237ea8c0a5df1afd8526eac4b6cee063 (diff) |
drm/i915: Add tracepoints
By adding tracepoint equivalents for WATCH_BUF/EXEC we are able to monitor
the lifetimes of objects, requests and significant events. These events can
then be probed using the tracing frameworks, such as systemtap and, in
particular, perf.
For example to record the stack trace for every GPU stall during a run, use
$ perf record -e i915:i915_gem_request_wait_begin -c 1 -g
And
$ perf report
to view the results.
[Updated to fix compilation issues caused.]
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Ben Gamari <bgamari@gmail.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | drivers/gpu/drm/i915/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 119 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_trace.h | 315 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_trace_points.c | 11 |
6 files changed, 447 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 5269dfa5f620..fa7b9be096bc 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
@@ -9,6 +9,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | |||
9 | i915_gem.o \ | 9 | i915_gem.o \ |
10 | i915_gem_debug.o \ | 10 | i915_gem_debug.o \ |
11 | i915_gem_tiling.o \ | 11 | i915_gem_tiling.o \ |
12 | i915_trace_points.o \ | ||
12 | intel_display.o \ | 13 | intel_display.o \ |
13 | intel_crt.o \ | 14 | intel_crt.o \ |
14 | intel_lvds.o \ | 15 | intel_lvds.o \ |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 59826c5b8760..ae7ec0390024 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "intel_drv.h" | 33 | #include "intel_drv.h" |
34 | #include "i915_drm.h" | 34 | #include "i915_drm.h" |
35 | #include "i915_drv.h" | 35 | #include "i915_drv.h" |
36 | #include "i915_trace.h" | ||
36 | 37 | ||
37 | /* Really want an OS-independent resettable timer. Would like to have | 38 | /* Really want an OS-independent resettable timer. Would like to have |
38 | * this loop run for (eg) 3 sec, but have the timer reset every time | 39 | * this loop run for (eg) 3 sec, but have the timer reset every time |
@@ -49,14 +50,18 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) | |||
49 | u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR; | 50 | u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR; |
50 | int i; | 51 | int i; |
51 | 52 | ||
53 | trace_i915_ring_wait_begin (dev); | ||
54 | |||
52 | for (i = 0; i < 100000; i++) { | 55 | for (i = 0; i < 100000; i++) { |
53 | ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; | 56 | ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; |
54 | acthd = I915_READ(acthd_reg); | 57 | acthd = I915_READ(acthd_reg); |
55 | ring->space = ring->head - (ring->tail + 8); | 58 | ring->space = ring->head - (ring->tail + 8); |
56 | if (ring->space < 0) | 59 | if (ring->space < 0) |
57 | ring->space += ring->Size; | 60 | ring->space += ring->Size; |
58 | if (ring->space >= n) | 61 | if (ring->space >= n) { |
62 | trace_i915_ring_wait_end (dev); | ||
59 | return 0; | 63 | return 0; |
64 | } | ||
60 | 65 | ||
61 | if (dev->primary->master) { | 66 | if (dev->primary->master) { |
62 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; | 67 | struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; |
@@ -76,6 +81,7 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) | |||
76 | 81 | ||
77 | } | 82 | } |
78 | 83 | ||
84 | trace_i915_ring_wait_end (dev); | ||
79 | return -EBUSY; | 85 | return -EBUSY; |
80 | } | 86 | } |
81 | 87 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index dea9ac069851..67e2cd5636ec 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "drm.h" | 29 | #include "drm.h" |
30 | #include "i915_drm.h" | 30 | #include "i915_drm.h" |
31 | #include "i915_drv.h" | 31 | #include "i915_drv.h" |
32 | #include "i915_trace.h" | ||
32 | #include "intel_drv.h" | 33 | #include "intel_drv.h" |
33 | #include <linux/swap.h> | 34 | #include <linux/swap.h> |
34 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
@@ -1618,8 +1619,14 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, | |||
1618 | 1619 | ||
1619 | if ((obj->write_domain & flush_domains) == | 1620 | if ((obj->write_domain & flush_domains) == |
1620 | obj->write_domain) { | 1621 | obj->write_domain) { |
1622 | uint32_t old_write_domain = obj->write_domain; | ||
1623 | |||
1621 | obj->write_domain = 0; | 1624 | obj->write_domain = 0; |
1622 | i915_gem_object_move_to_active(obj, seqno); | 1625 | i915_gem_object_move_to_active(obj, seqno); |
1626 | |||
1627 | trace_i915_gem_object_change_domain(obj, | ||
1628 | obj->read_domains, | ||
1629 | old_write_domain); | ||
1623 | } | 1630 | } |
1624 | } | 1631 | } |
1625 | 1632 | ||
@@ -1667,6 +1674,8 @@ i915_gem_retire_request(struct drm_device *dev, | |||
1667 | { | 1674 | { |
1668 | drm_i915_private_t *dev_priv = dev->dev_private; | 1675 | drm_i915_private_t *dev_priv = dev->dev_private; |
1669 | 1676 | ||
1677 | trace_i915_gem_request_retire(dev, request->seqno); | ||
1678 | |||
1670 | /* Move any buffers on the active list that are no longer referenced | 1679 | /* Move any buffers on the active list that are no longer referenced |
1671 | * by the ringbuffer to the flushing/inactive lists as appropriate. | 1680 | * by the ringbuffer to the flushing/inactive lists as appropriate. |
1672 | */ | 1681 | */ |
@@ -1810,6 +1819,8 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) | |||
1810 | i915_driver_irq_postinstall(dev); | 1819 | i915_driver_irq_postinstall(dev); |
1811 | } | 1820 | } |
1812 | 1821 | ||
1822 | trace_i915_gem_request_wait_begin(dev, seqno); | ||
1823 | |||
1813 | dev_priv->mm.waiting_gem_seqno = seqno; | 1824 | dev_priv->mm.waiting_gem_seqno = seqno; |
1814 | i915_user_irq_get(dev); | 1825 | i915_user_irq_get(dev); |
1815 | ret = wait_event_interruptible(dev_priv->irq_queue, | 1826 | ret = wait_event_interruptible(dev_priv->irq_queue, |
@@ -1818,6 +1829,8 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno) | |||
1818 | atomic_read(&dev_priv->mm.wedged)); | 1829 | atomic_read(&dev_priv->mm.wedged)); |
1819 | i915_user_irq_put(dev); | 1830 | i915_user_irq_put(dev); |
1820 | dev_priv->mm.waiting_gem_seqno = 0; | 1831 | dev_priv->mm.waiting_gem_seqno = 0; |
1832 | |||
1833 | trace_i915_gem_request_wait_end(dev, seqno); | ||
1821 | } | 1834 | } |
1822 | if (atomic_read(&dev_priv->mm.wedged)) | 1835 | if (atomic_read(&dev_priv->mm.wedged)) |
1823 | ret = -EIO; | 1836 | ret = -EIO; |
@@ -1850,6 +1863,8 @@ i915_gem_flush(struct drm_device *dev, | |||
1850 | DRM_INFO("%s: invalidate %08x flush %08x\n", __func__, | 1863 | DRM_INFO("%s: invalidate %08x flush %08x\n", __func__, |
1851 | invalidate_domains, flush_domains); | 1864 | invalidate_domains, flush_domains); |
1852 | #endif | 1865 | #endif |
1866 | trace_i915_gem_request_flush(dev, dev_priv->mm.next_gem_seqno, | ||
1867 | invalidate_domains, flush_domains); | ||
1853 | 1868 | ||
1854 | if (flush_domains & I915_GEM_DOMAIN_CPU) | 1869 | if (flush_domains & I915_GEM_DOMAIN_CPU) |
1855 | drm_agp_chipset_flush(dev); | 1870 | drm_agp_chipset_flush(dev); |
@@ -2003,6 +2018,8 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
2003 | if (!list_empty(&obj_priv->list)) | 2018 | if (!list_empty(&obj_priv->list)) |
2004 | list_del_init(&obj_priv->list); | 2019 | list_del_init(&obj_priv->list); |
2005 | 2020 | ||
2021 | trace_i915_gem_object_unbind(obj); | ||
2022 | |||
2006 | return 0; | 2023 | return 0; |
2007 | } | 2024 | } |
2008 | 2025 | ||
@@ -2452,6 +2469,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | |||
2452 | else | 2469 | else |
2453 | i830_write_fence_reg(reg); | 2470 | i830_write_fence_reg(reg); |
2454 | 2471 | ||
2472 | trace_i915_gem_object_get_fence(obj, i, obj_priv->tiling_mode); | ||
2473 | |||
2455 | return 0; | 2474 | return 0; |
2456 | } | 2475 | } |
2457 | 2476 | ||
@@ -2650,6 +2669,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2650 | BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); | 2669 | BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); |
2651 | BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); | 2670 | BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); |
2652 | 2671 | ||
2672 | trace_i915_gem_object_bind(obj, obj_priv->gtt_offset); | ||
2673 | |||
2653 | return 0; | 2674 | return 0; |
2654 | } | 2675 | } |
2655 | 2676 | ||
@@ -2665,6 +2686,8 @@ i915_gem_clflush_object(struct drm_gem_object *obj) | |||
2665 | if (obj_priv->pages == NULL) | 2686 | if (obj_priv->pages == NULL) |
2666 | return; | 2687 | return; |
2667 | 2688 | ||
2689 | trace_i915_gem_object_clflush(obj); | ||
2690 | |||
2668 | drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); | 2691 | drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); |
2669 | } | 2692 | } |
2670 | 2693 | ||
@@ -2674,21 +2697,29 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) | |||
2674 | { | 2697 | { |
2675 | struct drm_device *dev = obj->dev; | 2698 | struct drm_device *dev = obj->dev; |
2676 | uint32_t seqno; | 2699 | uint32_t seqno; |
2700 | uint32_t old_write_domain; | ||
2677 | 2701 | ||
2678 | if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) | 2702 | if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) |
2679 | return; | 2703 | return; |
2680 | 2704 | ||
2681 | /* Queue the GPU write cache flushing we need. */ | 2705 | /* Queue the GPU write cache flushing we need. */ |
2706 | old_write_domain = obj->write_domain; | ||
2682 | i915_gem_flush(dev, 0, obj->write_domain); | 2707 | i915_gem_flush(dev, 0, obj->write_domain); |
2683 | seqno = i915_add_request(dev, NULL, obj->write_domain); | 2708 | seqno = i915_add_request(dev, NULL, obj->write_domain); |
2684 | obj->write_domain = 0; | 2709 | obj->write_domain = 0; |
2685 | i915_gem_object_move_to_active(obj, seqno); | 2710 | i915_gem_object_move_to_active(obj, seqno); |
2711 | |||
2712 | trace_i915_gem_object_change_domain(obj, | ||
2713 | obj->read_domains, | ||
2714 | old_write_domain); | ||
2686 | } | 2715 | } |
2687 | 2716 | ||
2688 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2717 | /** Flushes the GTT write domain for the object if it's dirty. */ |
2689 | static void | 2718 | static void |
2690 | i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj) | 2719 | i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj) |
2691 | { | 2720 | { |
2721 | uint32_t old_write_domain; | ||
2722 | |||
2692 | if (obj->write_domain != I915_GEM_DOMAIN_GTT) | 2723 | if (obj->write_domain != I915_GEM_DOMAIN_GTT) |
2693 | return; | 2724 | return; |
2694 | 2725 | ||
@@ -2696,7 +2727,12 @@ i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj) | |||
2696 | * to it immediately go to main memory as far as we know, so there's | 2727 | * to it immediately go to main memory as far as we know, so there's |
2697 | * no chipset flush. It also doesn't land in render cache. | 2728 | * no chipset flush. It also doesn't land in render cache. |
2698 | */ | 2729 | */ |
2730 | old_write_domain = obj->write_domain; | ||
2699 | obj->write_domain = 0; | 2731 | obj->write_domain = 0; |
2732 | |||
2733 | trace_i915_gem_object_change_domain(obj, | ||
2734 | obj->read_domains, | ||
2735 | old_write_domain); | ||
2700 | } | 2736 | } |
2701 | 2737 | ||
2702 | /** Flushes the CPU write domain for the object if it's dirty. */ | 2738 | /** Flushes the CPU write domain for the object if it's dirty. */ |
@@ -2704,13 +2740,19 @@ static void | |||
2704 | i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) | 2740 | i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) |
2705 | { | 2741 | { |
2706 | struct drm_device *dev = obj->dev; | 2742 | struct drm_device *dev = obj->dev; |
2743 | uint32_t old_write_domain; | ||
2707 | 2744 | ||
2708 | if (obj->write_domain != I915_GEM_DOMAIN_CPU) | 2745 | if (obj->write_domain != I915_GEM_DOMAIN_CPU) |
2709 | return; | 2746 | return; |
2710 | 2747 | ||
2711 | i915_gem_clflush_object(obj); | 2748 | i915_gem_clflush_object(obj); |
2712 | drm_agp_chipset_flush(dev); | 2749 | drm_agp_chipset_flush(dev); |
2750 | old_write_domain = obj->write_domain; | ||
2713 | obj->write_domain = 0; | 2751 | obj->write_domain = 0; |
2752 | |||
2753 | trace_i915_gem_object_change_domain(obj, | ||
2754 | obj->read_domains, | ||
2755 | old_write_domain); | ||
2714 | } | 2756 | } |
2715 | 2757 | ||
2716 | /** | 2758 | /** |
@@ -2723,6 +2765,7 @@ int | |||
2723 | i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | 2765 | i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) |
2724 | { | 2766 | { |
2725 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2767 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
2768 | uint32_t old_write_domain, old_read_domains; | ||
2726 | int ret; | 2769 | int ret; |
2727 | 2770 | ||
2728 | /* Not valid to be called on unbound objects. */ | 2771 | /* Not valid to be called on unbound objects. */ |
@@ -2735,6 +2778,9 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
2735 | if (ret != 0) | 2778 | if (ret != 0) |
2736 | return ret; | 2779 | return ret; |
2737 | 2780 | ||
2781 | old_write_domain = obj->write_domain; | ||
2782 | old_read_domains = obj->read_domains; | ||
2783 | |||
2738 | /* If we're writing through the GTT domain, then CPU and GPU caches | 2784 | /* If we're writing through the GTT domain, then CPU and GPU caches |
2739 | * will need to be invalidated at next use. | 2785 | * will need to be invalidated at next use. |
2740 | */ | 2786 | */ |
@@ -2753,6 +2799,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
2753 | obj_priv->dirty = 1; | 2799 | obj_priv->dirty = 1; |
2754 | } | 2800 | } |
2755 | 2801 | ||
2802 | trace_i915_gem_object_change_domain(obj, | ||
2803 | old_read_domains, | ||
2804 | old_write_domain); | ||
2805 | |||
2756 | return 0; | 2806 | return 0; |
2757 | } | 2807 | } |
2758 | 2808 | ||
@@ -2765,6 +2815,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
2765 | static int | 2815 | static int |
2766 | i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | 2816 | i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) |
2767 | { | 2817 | { |
2818 | uint32_t old_write_domain, old_read_domains; | ||
2768 | int ret; | 2819 | int ret; |
2769 | 2820 | ||
2770 | i915_gem_object_flush_gpu_write_domain(obj); | 2821 | i915_gem_object_flush_gpu_write_domain(obj); |
@@ -2780,6 +2831,9 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2780 | */ | 2831 | */ |
2781 | i915_gem_object_set_to_full_cpu_read_domain(obj); | 2832 | i915_gem_object_set_to_full_cpu_read_domain(obj); |
2782 | 2833 | ||
2834 | old_write_domain = obj->write_domain; | ||
2835 | old_read_domains = obj->read_domains; | ||
2836 | |||
2783 | /* Flush the CPU cache if it's still invalid. */ | 2837 | /* Flush the CPU cache if it's still invalid. */ |
2784 | if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) { | 2838 | if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) { |
2785 | i915_gem_clflush_object(obj); | 2839 | i915_gem_clflush_object(obj); |
@@ -2800,6 +2854,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2800 | obj->write_domain = I915_GEM_DOMAIN_CPU; | 2854 | obj->write_domain = I915_GEM_DOMAIN_CPU; |
2801 | } | 2855 | } |
2802 | 2856 | ||
2857 | trace_i915_gem_object_change_domain(obj, | ||
2858 | old_read_domains, | ||
2859 | old_write_domain); | ||
2860 | |||
2803 | return 0; | 2861 | return 0; |
2804 | } | 2862 | } |
2805 | 2863 | ||
@@ -2921,6 +2979,7 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
2921 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2979 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
2922 | uint32_t invalidate_domains = 0; | 2980 | uint32_t invalidate_domains = 0; |
2923 | uint32_t flush_domains = 0; | 2981 | uint32_t flush_domains = 0; |
2982 | uint32_t old_read_domains; | ||
2924 | 2983 | ||
2925 | BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU); | 2984 | BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU); |
2926 | BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU); | 2985 | BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU); |
@@ -2967,6 +3026,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
2967 | i915_gem_clflush_object(obj); | 3026 | i915_gem_clflush_object(obj); |
2968 | } | 3027 | } |
2969 | 3028 | ||
3029 | old_read_domains = obj->read_domains; | ||
3030 | |||
2970 | /* The actual obj->write_domain will be updated with | 3031 | /* The actual obj->write_domain will be updated with |
2971 | * pending_write_domain after we emit the accumulated flush for all | 3032 | * pending_write_domain after we emit the accumulated flush for all |
2972 | * of our domain changes in execbuffers (which clears objects' | 3033 | * of our domain changes in execbuffers (which clears objects' |
@@ -2985,6 +3046,10 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
2985 | obj->read_domains, obj->write_domain, | 3046 | obj->read_domains, obj->write_domain, |
2986 | dev->invalidate_domains, dev->flush_domains); | 3047 | dev->invalidate_domains, dev->flush_domains); |
2987 | #endif | 3048 | #endif |
3049 | |||
3050 | trace_i915_gem_object_change_domain(obj, | ||
3051 | old_read_domains, | ||
3052 | obj->write_domain); | ||
2988 | } | 3053 | } |
2989 | 3054 | ||
2990 | /** | 3055 | /** |
@@ -3037,6 +3102,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
3037 | uint64_t offset, uint64_t size) | 3102 | uint64_t offset, uint64_t size) |
3038 | { | 3103 | { |
3039 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 3104 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
3105 | uint32_t old_read_domains; | ||
3040 | int i, ret; | 3106 | int i, ret; |
3041 | 3107 | ||
3042 | if (offset == 0 && size == obj->size) | 3108 | if (offset == 0 && size == obj->size) |
@@ -3083,8 +3149,13 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
3083 | */ | 3149 | */ |
3084 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0); | 3150 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0); |
3085 | 3151 | ||
3152 | old_read_domains = obj->read_domains; | ||
3086 | obj->read_domains |= I915_GEM_DOMAIN_CPU; | 3153 | obj->read_domains |= I915_GEM_DOMAIN_CPU; |
3087 | 3154 | ||
3155 | trace_i915_gem_object_change_domain(obj, | ||
3156 | old_read_domains, | ||
3157 | obj->write_domain); | ||
3158 | |||
3088 | return 0; | 3159 | return 0; |
3089 | } | 3160 | } |
3090 | 3161 | ||
@@ -3282,6 +3353,8 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev, | |||
3282 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; | 3353 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; |
3283 | exec_len = (uint32_t) exec->batch_len; | 3354 | exec_len = (uint32_t) exec->batch_len; |
3284 | 3355 | ||
3356 | trace_i915_gem_request_submit(dev, dev_priv->mm.next_gem_seqno); | ||
3357 | |||
3285 | count = nbox ? nbox : 1; | 3358 | count = nbox ? nbox : 1; |
3286 | 3359 | ||
3287 | for (i = 0; i < count; i++) { | 3360 | for (i = 0; i < count; i++) { |
@@ -3660,8 +3733,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
3660 | 3733 | ||
3661 | for (i = 0; i < args->buffer_count; i++) { | 3734 | for (i = 0; i < args->buffer_count; i++) { |
3662 | struct drm_gem_object *obj = object_list[i]; | 3735 | struct drm_gem_object *obj = object_list[i]; |
3736 | uint32_t old_write_domain = obj->write_domain; | ||
3663 | 3737 | ||
3664 | obj->write_domain = obj->pending_write_domain; | 3738 | obj->write_domain = obj->pending_write_domain; |
3739 | trace_i915_gem_object_change_domain(obj, | ||
3740 | obj->read_domains, | ||
3741 | old_write_domain); | ||
3665 | } | 3742 | } |
3666 | 3743 | ||
3667 | i915_verify_inactive(dev, __FILE__, __LINE__); | 3744 | i915_verify_inactive(dev, __FILE__, __LINE__); |
@@ -4050,6 +4127,8 @@ int i915_gem_init_object(struct drm_gem_object *obj) | |||
4050 | INIT_LIST_HEAD(&obj_priv->fence_list); | 4127 | INIT_LIST_HEAD(&obj_priv->fence_list); |
4051 | obj_priv->madv = I915_MADV_WILLNEED; | 4128 | obj_priv->madv = I915_MADV_WILLNEED; |
4052 | 4129 | ||
4130 | trace_i915_gem_object_create(obj); | ||
4131 | |||
4053 | return 0; | 4132 | return 0; |
4054 | } | 4133 | } |
4055 | 4134 | ||
@@ -4058,6 +4137,8 @@ void i915_gem_free_object(struct drm_gem_object *obj) | |||
4058 | struct drm_device *dev = obj->dev; | 4137 | struct drm_device *dev = obj->dev; |
4059 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 4138 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
4060 | 4139 | ||
4140 | trace_i915_gem_object_destroy(obj); | ||
4141 | |||
4061 | while (obj_priv->pin_count > 0) | 4142 | while (obj_priv->pin_count > 0) |
4062 | i915_gem_object_unpin(obj); | 4143 | i915_gem_object_unpin(obj); |
4063 | 4144 | ||
@@ -4186,24 +4267,36 @@ i915_gem_idle(struct drm_device *dev) | |||
4186 | * the GPU domains and just stuff them onto inactive. | 4267 | * the GPU domains and just stuff them onto inactive. |
4187 | */ | 4268 | */ |
4188 | while (!list_empty(&dev_priv->mm.active_list)) { | 4269 | while (!list_empty(&dev_priv->mm.active_list)) { |
4189 | struct drm_i915_gem_object *obj_priv; | 4270 | struct drm_gem_object *obj; |
4271 | uint32_t old_write_domain; | ||
4190 | 4272 | ||
4191 | obj_priv = list_first_entry(&dev_priv->mm.active_list, | 4273 | obj = list_first_entry(&dev_priv->mm.active_list, |
4192 | struct drm_i915_gem_object, | 4274 | struct drm_i915_gem_object, |
4193 | list); | 4275 | list)->obj; |
4194 | obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; | 4276 | old_write_domain = obj->write_domain; |
4195 | i915_gem_object_move_to_inactive(obj_priv->obj); | 4277 | obj->write_domain &= ~I915_GEM_GPU_DOMAINS; |
4278 | i915_gem_object_move_to_inactive(obj); | ||
4279 | |||
4280 | trace_i915_gem_object_change_domain(obj, | ||
4281 | obj->read_domains, | ||
4282 | old_write_domain); | ||
4196 | } | 4283 | } |
4197 | spin_unlock(&dev_priv->mm.active_list_lock); | 4284 | spin_unlock(&dev_priv->mm.active_list_lock); |
4198 | 4285 | ||
4199 | while (!list_empty(&dev_priv->mm.flushing_list)) { | 4286 | while (!list_empty(&dev_priv->mm.flushing_list)) { |
4200 | struct drm_i915_gem_object *obj_priv; | 4287 | struct drm_gem_object *obj; |
4201 | 4288 | uint32_t old_write_domain; | |
4202 | obj_priv = list_first_entry(&dev_priv->mm.flushing_list, | 4289 | |
4203 | struct drm_i915_gem_object, | 4290 | obj = list_first_entry(&dev_priv->mm.flushing_list, |
4204 | list); | 4291 | struct drm_i915_gem_object, |
4205 | obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; | 4292 | list)->obj; |
4206 | i915_gem_object_move_to_inactive(obj_priv->obj); | 4293 | old_write_domain = obj->write_domain; |
4294 | obj->write_domain &= ~I915_GEM_GPU_DOMAINS; | ||
4295 | i915_gem_object_move_to_inactive(obj); | ||
4296 | |||
4297 | trace_i915_gem_object_change_domain(obj, | ||
4298 | obj->read_domains, | ||
4299 | old_write_domain); | ||
4207 | } | 4300 | } |
4208 | 4301 | ||
4209 | 4302 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 13e664ddb611..4dfeec7cdd42 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "drm.h" | 31 | #include "drm.h" |
32 | #include "i915_drm.h" | 32 | #include "i915_drm.h" |
33 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
34 | #include "i915_trace.h" | ||
34 | #include "intel_drv.h" | 35 | #include "intel_drv.h" |
35 | 36 | ||
36 | #define MAX_NOPID ((u32)~0) | 37 | #define MAX_NOPID ((u32)~0) |
@@ -279,7 +280,9 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) | |||
279 | } | 280 | } |
280 | 281 | ||
281 | if (gt_iir & GT_USER_INTERRUPT) { | 282 | if (gt_iir & GT_USER_INTERRUPT) { |
282 | dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); | 283 | u32 seqno = i915_get_gem_seqno(dev); |
284 | dev_priv->mm.irq_gem_seqno = seqno; | ||
285 | trace_i915_gem_request_complete(dev, seqno); | ||
283 | DRM_WAKEUP(&dev_priv->irq_queue); | 286 | DRM_WAKEUP(&dev_priv->irq_queue); |
284 | } | 287 | } |
285 | 288 | ||
@@ -622,7 +625,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
622 | } | 625 | } |
623 | 626 | ||
624 | if (iir & I915_USER_INTERRUPT) { | 627 | if (iir & I915_USER_INTERRUPT) { |
625 | dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); | 628 | u32 seqno = i915_get_gem_seqno(dev); |
629 | dev_priv->mm.irq_gem_seqno = seqno; | ||
630 | trace_i915_gem_request_complete(dev, seqno); | ||
626 | DRM_WAKEUP(&dev_priv->irq_queue); | 631 | DRM_WAKEUP(&dev_priv->irq_queue); |
627 | dev_priv->hangcheck_count = 0; | 632 | dev_priv->hangcheck_count = 0; |
628 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | 633 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); |
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h new file mode 100644 index 000000000000..5567a40816f3 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_trace.h | |||
@@ -0,0 +1,315 @@ | |||
1 | #if !defined(_I915_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define _I915_TRACE_H_ | ||
3 | |||
4 | #include <linux/stringify.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/tracepoint.h> | ||
7 | |||
8 | #include <drm/drmP.h> | ||
9 | |||
10 | #undef TRACE_SYSTEM | ||
11 | #define TRACE_SYSTEM i915 | ||
12 | #define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM) | ||
13 | #define TRACE_INCLUDE_FILE i915_trace | ||
14 | |||
15 | /* object tracking */ | ||
16 | |||
17 | TRACE_EVENT(i915_gem_object_create, | ||
18 | |||
19 | TP_PROTO(struct drm_gem_object *obj), | ||
20 | |||
21 | TP_ARGS(obj), | ||
22 | |||
23 | TP_STRUCT__entry( | ||
24 | __field(struct drm_gem_object *, obj) | ||
25 | __field(u32, size) | ||
26 | ), | ||
27 | |||
28 | TP_fast_assign( | ||
29 | __entry->obj = obj; | ||
30 | __entry->size = obj->size; | ||
31 | ), | ||
32 | |||
33 | TP_printk("obj=%p, size=%u", __entry->obj, __entry->size) | ||
34 | ); | ||
35 | |||
36 | TRACE_EVENT(i915_gem_object_bind, | ||
37 | |||
38 | TP_PROTO(struct drm_gem_object *obj, u32 gtt_offset), | ||
39 | |||
40 | TP_ARGS(obj, gtt_offset), | ||
41 | |||
42 | TP_STRUCT__entry( | ||
43 | __field(struct drm_gem_object *, obj) | ||
44 | __field(u32, gtt_offset) | ||
45 | ), | ||
46 | |||
47 | TP_fast_assign( | ||
48 | __entry->obj = obj; | ||
49 | __entry->gtt_offset = gtt_offset; | ||
50 | ), | ||
51 | |||
52 | TP_printk("obj=%p, gtt_offset=%08x", | ||
53 | __entry->obj, __entry->gtt_offset) | ||
54 | ); | ||
55 | |||
56 | TRACE_EVENT(i915_gem_object_clflush, | ||
57 | |||
58 | TP_PROTO(struct drm_gem_object *obj), | ||
59 | |||
60 | TP_ARGS(obj), | ||
61 | |||
62 | TP_STRUCT__entry( | ||
63 | __field(struct drm_gem_object *, obj) | ||
64 | ), | ||
65 | |||
66 | TP_fast_assign( | ||
67 | __entry->obj = obj; | ||
68 | ), | ||
69 | |||
70 | TP_printk("obj=%p", __entry->obj) | ||
71 | ); | ||
72 | |||
73 | TRACE_EVENT(i915_gem_object_change_domain, | ||
74 | |||
75 | TP_PROTO(struct drm_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain), | ||
76 | |||
77 | TP_ARGS(obj, old_read_domains, old_write_domain), | ||
78 | |||
79 | TP_STRUCT__entry( | ||
80 | __field(struct drm_gem_object *, obj) | ||
81 | __field(u32, read_domains) | ||
82 | __field(u32, write_domain) | ||
83 | ), | ||
84 | |||
85 | TP_fast_assign( | ||
86 | __entry->obj = obj; | ||
87 | __entry->read_domains = obj->read_domains | (old_read_domains << 16); | ||
88 | __entry->write_domain = obj->write_domain | (old_write_domain << 16); | ||
89 | ), | ||
90 | |||
91 | TP_printk("obj=%p, read=%04x, write=%04x", | ||
92 | __entry->obj, | ||
93 | __entry->read_domains, __entry->write_domain) | ||
94 | ); | ||
95 | |||
96 | TRACE_EVENT(i915_gem_object_get_fence, | ||
97 | |||
98 | TP_PROTO(struct drm_gem_object *obj, int fence, int tiling_mode), | ||
99 | |||
100 | TP_ARGS(obj, fence, tiling_mode), | ||
101 | |||
102 | TP_STRUCT__entry( | ||
103 | __field(struct drm_gem_object *, obj) | ||
104 | __field(int, fence) | ||
105 | __field(int, tiling_mode) | ||
106 | ), | ||
107 | |||
108 | TP_fast_assign( | ||
109 | __entry->obj = obj; | ||
110 | __entry->fence = fence; | ||
111 | __entry->tiling_mode = tiling_mode; | ||
112 | ), | ||
113 | |||
114 | TP_printk("obj=%p, fence=%d, tiling=%d", | ||
115 | __entry->obj, __entry->fence, __entry->tiling_mode) | ||
116 | ); | ||
117 | |||
118 | TRACE_EVENT(i915_gem_object_unbind, | ||
119 | |||
120 | TP_PROTO(struct drm_gem_object *obj), | ||
121 | |||
122 | TP_ARGS(obj), | ||
123 | |||
124 | TP_STRUCT__entry( | ||
125 | __field(struct drm_gem_object *, obj) | ||
126 | ), | ||
127 | |||
128 | TP_fast_assign( | ||
129 | __entry->obj = obj; | ||
130 | ), | ||
131 | |||
132 | TP_printk("obj=%p", __entry->obj) | ||
133 | ); | ||
134 | |||
135 | TRACE_EVENT(i915_gem_object_destroy, | ||
136 | |||
137 | TP_PROTO(struct drm_gem_object *obj), | ||
138 | |||
139 | TP_ARGS(obj), | ||
140 | |||
141 | TP_STRUCT__entry( | ||
142 | __field(struct drm_gem_object *, obj) | ||
143 | ), | ||
144 | |||
145 | TP_fast_assign( | ||
146 | __entry->obj = obj; | ||
147 | ), | ||
148 | |||
149 | TP_printk("obj=%p", __entry->obj) | ||
150 | ); | ||
151 | |||
152 | /* batch tracing */ | ||
153 | |||
154 | TRACE_EVENT(i915_gem_request_submit, | ||
155 | |||
156 | TP_PROTO(struct drm_device *dev, u32 seqno), | ||
157 | |||
158 | TP_ARGS(dev, seqno), | ||
159 | |||
160 | TP_STRUCT__entry( | ||
161 | __field(struct drm_device *, dev) | ||
162 | __field(u32, seqno) | ||
163 | ), | ||
164 | |||
165 | TP_fast_assign( | ||
166 | __entry->dev = dev; | ||
167 | __entry->seqno = seqno; | ||
168 | ), | ||
169 | |||
170 | TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno) | ||
171 | ); | ||
172 | |||
173 | TRACE_EVENT(i915_gem_request_flush, | ||
174 | |||
175 | TP_PROTO(struct drm_device *dev, u32 seqno, | ||
176 | u32 flush_domains, u32 invalidate_domains), | ||
177 | |||
178 | TP_ARGS(dev, seqno, flush_domains, invalidate_domains), | ||
179 | |||
180 | TP_STRUCT__entry( | ||
181 | __field(struct drm_device *, dev) | ||
182 | __field(u32, seqno) | ||
183 | __field(u32, flush_domains) | ||
184 | __field(u32, invalidate_domains) | ||
185 | ), | ||
186 | |||
187 | TP_fast_assign( | ||
188 | __entry->dev = dev; | ||
189 | __entry->seqno = seqno; | ||
190 | __entry->flush_domains = flush_domains; | ||
191 | __entry->invalidate_domains = invalidate_domains; | ||
192 | ), | ||
193 | |||
194 | TP_printk("dev=%p, seqno=%u, flush=%04x, invalidate=%04x", | ||
195 | __entry->dev, __entry->seqno, | ||
196 | __entry->flush_domains, __entry->invalidate_domains) | ||
197 | ); | ||
198 | |||
199 | |||
200 | TRACE_EVENT(i915_gem_request_complete, | ||
201 | |||
202 | TP_PROTO(struct drm_device *dev, u32 seqno), | ||
203 | |||
204 | TP_ARGS(dev, seqno), | ||
205 | |||
206 | TP_STRUCT__entry( | ||
207 | __field(struct drm_device *, dev) | ||
208 | __field(u32, seqno) | ||
209 | ), | ||
210 | |||
211 | TP_fast_assign( | ||
212 | __entry->dev = dev; | ||
213 | __entry->seqno = seqno; | ||
214 | ), | ||
215 | |||
216 | TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno) | ||
217 | ); | ||
218 | |||
219 | TRACE_EVENT(i915_gem_request_retire, | ||
220 | |||
221 | TP_PROTO(struct drm_device *dev, u32 seqno), | ||
222 | |||
223 | TP_ARGS(dev, seqno), | ||
224 | |||
225 | TP_STRUCT__entry( | ||
226 | __field(struct drm_device *, dev) | ||
227 | __field(u32, seqno) | ||
228 | ), | ||
229 | |||
230 | TP_fast_assign( | ||
231 | __entry->dev = dev; | ||
232 | __entry->seqno = seqno; | ||
233 | ), | ||
234 | |||
235 | TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno) | ||
236 | ); | ||
237 | |||
238 | TRACE_EVENT(i915_gem_request_wait_begin, | ||
239 | |||
240 | TP_PROTO(struct drm_device *dev, u32 seqno), | ||
241 | |||
242 | TP_ARGS(dev, seqno), | ||
243 | |||
244 | TP_STRUCT__entry( | ||
245 | __field(struct drm_device *, dev) | ||
246 | __field(u32, seqno) | ||
247 | ), | ||
248 | |||
249 | TP_fast_assign( | ||
250 | __entry->dev = dev; | ||
251 | __entry->seqno = seqno; | ||
252 | ), | ||
253 | |||
254 | TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno) | ||
255 | ); | ||
256 | |||
257 | TRACE_EVENT(i915_gem_request_wait_end, | ||
258 | |||
259 | TP_PROTO(struct drm_device *dev, u32 seqno), | ||
260 | |||
261 | TP_ARGS(dev, seqno), | ||
262 | |||
263 | TP_STRUCT__entry( | ||
264 | __field(struct drm_device *, dev) | ||
265 | __field(u32, seqno) | ||
266 | ), | ||
267 | |||
268 | TP_fast_assign( | ||
269 | __entry->dev = dev; | ||
270 | __entry->seqno = seqno; | ||
271 | ), | ||
272 | |||
273 | TP_printk("dev=%p, seqno=%u", __entry->dev, __entry->seqno) | ||
274 | ); | ||
275 | |||
276 | TRACE_EVENT(i915_ring_wait_begin, | ||
277 | |||
278 | TP_PROTO(struct drm_device *dev), | ||
279 | |||
280 | TP_ARGS(dev), | ||
281 | |||
282 | TP_STRUCT__entry( | ||
283 | __field(struct drm_device *, dev) | ||
284 | ), | ||
285 | |||
286 | TP_fast_assign( | ||
287 | __entry->dev = dev; | ||
288 | ), | ||
289 | |||
290 | TP_printk("dev=%p", __entry->dev) | ||
291 | ); | ||
292 | |||
293 | TRACE_EVENT(i915_ring_wait_end, | ||
294 | |||
295 | TP_PROTO(struct drm_device *dev), | ||
296 | |||
297 | TP_ARGS(dev), | ||
298 | |||
299 | TP_STRUCT__entry( | ||
300 | __field(struct drm_device *, dev) | ||
301 | ), | ||
302 | |||
303 | TP_fast_assign( | ||
304 | __entry->dev = dev; | ||
305 | ), | ||
306 | |||
307 | TP_printk("dev=%p", __entry->dev) | ||
308 | ); | ||
309 | |||
310 | #endif /* _I915_TRACE_H_ */ | ||
311 | |||
312 | /* This part must be outside protection */ | ||
313 | #undef TRACE_INCLUDE_PATH | ||
314 | #define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/i915 | ||
315 | #include <trace/define_trace.h> | ||
diff --git a/drivers/gpu/drm/i915/i915_trace_points.c b/drivers/gpu/drm/i915/i915_trace_points.c new file mode 100644 index 000000000000..ead876eb6ea0 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_trace_points.c | |||
@@ -0,0 +1,11 @@ | |||
1 | /* | ||
2 | * Copyright © 2009 Intel Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Chris Wilson <chris@chris-wilson.co.uk> | ||
6 | */ | ||
7 | |||
8 | #include "i915_drv.h" | ||
9 | |||
10 | #define CREATE_TRACE_POINTS | ||
11 | #include "i915_trace.h" | ||