summaryrefslogtreecommitdiffstats
path: root/meta-moblin/packages/linux/linux-moblin-2.6.27/0016-i915-Use-struct_mutex-to-protect-ring-in-GEM-mode.patch
diff options
context:
space:
mode:
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.patch205
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 @@
1commit 8a524209fce67d3b6d2e831b5dad4eced796ce98
2Author: Eric Anholt <eric@anholt.net>
3Date: 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
15diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
16index 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,
94diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
95index 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))
134diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
135index 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);
147diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
148index 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");