diff options
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.27/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.27/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.27/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch b/meta-moblin/packages/linux/linux-moblin-2.6.27/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch new file mode 100644 index 0000000000..910f37e9c5 --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.27/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch | |||
@@ -0,0 +1,205 @@ | |||
1 | commit 8a524209fce67d3b6d2e831b5dad4eced796ce98 | ||
2 | Author: Eric Anholt <eric@anholt.net> | ||
3 | Date: Mon Sep 1 16:45:29 2008 -0700 | ||
4 | |||
5 | i915: Use struct_mutex to protect ring in GEM mode. | ||
6 | |||
7 | In the conversion for GEM, we had stopped using the hardware lock to protect | ||
8 | ring usage, since it was all internal to the DRM now. However, some paths | ||
9 | weren't converted to using struct_mutex to prevent multiple threads from | ||
10 | concurrently working on the ring, in particular between the vblank swap handler | ||
11 | and ioctls. | ||
12 | |||
13 | Signed-off-by: Eric Anholt <eric@anholt.net> | ||
14 | |||
15 | diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c | ||
16 | index 205d21e..25f59c1 100644 | ||
17 | --- a/drivers/gpu/drm/i915/i915_dma.c | ||
18 | +++ b/drivers/gpu/drm/i915/i915_dma.c | ||
19 | @@ -588,9 +588,15 @@ static int i915_quiescent(struct drm_device * dev) | ||
20 | static int i915_flush_ioctl(struct drm_device *dev, void *data, | ||
21 | struct drm_file *file_priv) | ||
22 | { | ||
23 | - LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
24 | + int ret; | ||
25 | + | ||
26 | + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
27 | |||
28 | - return i915_quiescent(dev); | ||
29 | + mutex_lock(&dev->struct_mutex); | ||
30 | + ret = i915_quiescent(dev); | ||
31 | + mutex_unlock(&dev->struct_mutex); | ||
32 | + | ||
33 | + return ret; | ||
34 | } | ||
35 | |||
36 | static int i915_batchbuffer(struct drm_device *dev, void *data, | ||
37 | @@ -611,14 +617,16 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, | ||
38 | DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n", | ||
39 | batch->start, batch->used, batch->num_cliprects); | ||
40 | |||
41 | - LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
42 | + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
43 | |||
44 | if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, | ||
45 | batch->num_cliprects * | ||
46 | sizeof(struct drm_clip_rect))) | ||
47 | return -EFAULT; | ||
48 | |||
49 | + mutex_lock(&dev->struct_mutex); | ||
50 | ret = i915_dispatch_batchbuffer(dev, batch); | ||
51 | + mutex_unlock(&dev->struct_mutex); | ||
52 | |||
53 | sarea_priv->last_dispatch = (int)hw_status[5]; | ||
54 | return ret; | ||
55 | @@ -637,7 +645,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | ||
56 | DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", | ||
57 | cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects); | ||
58 | |||
59 | - LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
60 | + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
61 | |||
62 | if (cmdbuf->num_cliprects && | ||
63 | DRM_VERIFYAREA_READ(cmdbuf->cliprects, | ||
64 | @@ -647,7 +655,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | ||
65 | return -EFAULT; | ||
66 | } | ||
67 | |||
68 | + mutex_lock(&dev->struct_mutex); | ||
69 | ret = i915_dispatch_cmdbuffer(dev, cmdbuf); | ||
70 | + mutex_unlock(&dev->struct_mutex); | ||
71 | if (ret) { | ||
72 | DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); | ||
73 | return ret; | ||
74 | @@ -660,11 +670,17 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, | ||
75 | static int i915_flip_bufs(struct drm_device *dev, void *data, | ||
76 | struct drm_file *file_priv) | ||
77 | { | ||
78 | + int ret; | ||
79 | + | ||
80 | DRM_DEBUG("%s\n", __FUNCTION__); | ||
81 | |||
82 | - LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
83 | + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
84 | |||
85 | - return i915_dispatch_flip(dev); | ||
86 | + mutex_lock(&dev->struct_mutex); | ||
87 | + ret = i915_dispatch_flip(dev); | ||
88 | + mutex_unlock(&dev->struct_mutex); | ||
89 | + | ||
90 | + return ret; | ||
91 | } | ||
92 | |||
93 | static int i915_getparam(struct drm_device *dev, void *data, | ||
94 | diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h | ||
95 | index 87b071a..8547f0a 100644 | ||
96 | --- a/drivers/gpu/drm/i915/i915_drv.h | ||
97 | +++ b/drivers/gpu/drm/i915/i915_drv.h | ||
98 | @@ -285,6 +285,9 @@ typedef struct drm_i915_private { | ||
99 | */ | ||
100 | struct delayed_work retire_work; | ||
101 | |||
102 | + /** Work task for vblank-related ring access */ | ||
103 | + struct work_struct vblank_work; | ||
104 | + | ||
105 | uint32_t next_gem_seqno; | ||
106 | |||
107 | /** | ||
108 | @@ -435,6 +438,7 @@ extern int i915_irq_wait(struct drm_device *dev, void *data, | ||
109 | void i915_user_irq_get(struct drm_device *dev); | ||
110 | void i915_user_irq_put(struct drm_device *dev); | ||
111 | |||
112 | +extern void i915_gem_vblank_work_handler(struct work_struct *work); | ||
113 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); | ||
114 | extern void i915_driver_irq_preinstall(struct drm_device * dev); | ||
115 | extern int i915_driver_irq_postinstall(struct drm_device *dev); | ||
116 | @@ -538,6 +542,17 @@ extern void intel_opregion_free(struct drm_device *dev); | ||
117 | extern void opregion_asle_intr(struct drm_device *dev); | ||
118 | extern void opregion_enable_asle(struct drm_device *dev); | ||
119 | |||
120 | +/** | ||
121 | + * Lock test for when it's just for synchronization of ring access. | ||
122 | + * | ||
123 | + * In that case, we don't need to do it when GEM is initialized as nobody else | ||
124 | + * has access to the ring. | ||
125 | + */ | ||
126 | +#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \ | ||
127 | + if (((drm_i915_private_t *)dev->dev_private)->ring.ring_obj == NULL) \ | ||
128 | + LOCK_TEST_WITH_RETURN(dev, file_priv); \ | ||
129 | +} while (0) | ||
130 | + | ||
131 | #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) | ||
132 | #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) | ||
133 | #define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg)) | ||
134 | diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c | ||
135 | index 90ae8a0..bb6e5a3 100644 | ||
136 | --- a/drivers/gpu/drm/i915/i915_gem.c | ||
137 | +++ b/drivers/gpu/drm/i915/i915_gem.c | ||
138 | @@ -2491,6 +2491,8 @@ i915_gem_load(struct drm_device *dev) | ||
139 | INIT_LIST_HEAD(&dev_priv->mm.request_list); | ||
140 | INIT_DELAYED_WORK(&dev_priv->mm.retire_work, | ||
141 | i915_gem_retire_work_handler); | ||
142 | + INIT_WORK(&dev_priv->mm.vblank_work, | ||
143 | + i915_gem_vblank_work_handler); | ||
144 | dev_priv->mm.next_gem_seqno = 1; | ||
145 | |||
146 | i915_gem_detect_bit_6_swizzle(dev); | ||
147 | diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c | ||
148 | index f295bdf..d04c526 100644 | ||
149 | --- a/drivers/gpu/drm/i915/i915_irq.c | ||
150 | +++ b/drivers/gpu/drm/i915/i915_irq.c | ||
151 | @@ -349,6 +349,21 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane) | ||
152 | return count; | ||
153 | } | ||
154 | |||
155 | +void | ||
156 | +i915_gem_vblank_work_handler(struct work_struct *work) | ||
157 | +{ | ||
158 | + drm_i915_private_t *dev_priv; | ||
159 | + struct drm_device *dev; | ||
160 | + | ||
161 | + dev_priv = container_of(work, drm_i915_private_t, | ||
162 | + mm.vblank_work); | ||
163 | + dev = dev_priv->dev; | ||
164 | + | ||
165 | + mutex_lock(&dev->struct_mutex); | ||
166 | + i915_vblank_tasklet(dev); | ||
167 | + mutex_unlock(&dev->struct_mutex); | ||
168 | +} | ||
169 | + | ||
170 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | ||
171 | { | ||
172 | struct drm_device *dev = (struct drm_device *) arg; | ||
173 | @@ -422,8 +437,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | ||
174 | if (iir & I915_ASLE_INTERRUPT) | ||
175 | opregion_asle_intr(dev); | ||
176 | |||
177 | - if (vblank && dev_priv->swaps_pending > 0) | ||
178 | - drm_locked_tasklet(dev, i915_vblank_tasklet); | ||
179 | + if (vblank && dev_priv->swaps_pending > 0) { | ||
180 | + if (dev_priv->ring.ring_obj == NULL) | ||
181 | + drm_locked_tasklet(dev, i915_vblank_tasklet); | ||
182 | + else | ||
183 | + schedule_work(&dev_priv->mm.vblank_work); | ||
184 | + } | ||
185 | |||
186 | return IRQ_HANDLED; | ||
187 | } | ||
188 | @@ -514,14 +533,15 @@ int i915_irq_emit(struct drm_device *dev, void *data, | ||
189 | drm_i915_irq_emit_t *emit = data; | ||
190 | int result; | ||
191 | |||
192 | - LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
193 | + RING_LOCK_TEST_WITH_RETURN(dev, file_priv); | ||
194 | |||
195 | if (!dev_priv) { | ||
196 | DRM_ERROR("called with no initialization\n"); | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | - | ||
200 | + mutex_lock(&dev->struct_mutex); | ||
201 | result = i915_emit_irq(dev); | ||
202 | + mutex_unlock(&dev->struct_mutex); | ||
203 | |||
204 | if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { | ||
205 | DRM_ERROR("copy_to_user\n"); | ||