]> code.ossystems Code Review - openembedded-core.git/blob
910f37e9c588e5283929b6f0922426c8abeddc50
[openembedded-core.git] /
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");