aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-11-27 23:22:24 -0500
committerDave Airlie <airlied@linux.ie>2008-12-29 02:47:22 -0500
commit7c1c2871a6a3a114853ec6836e9035ac1c0c7f7a (patch)
tree1b5debcc86ff20bd5e11b42ea5c52da42214e376 /drivers/gpu/drm/i915
parente7f7ab45ebcb54fd5f814ea15ea079e079662f67 (diff)
drm: move to kref per-master structures.
This is step one towards having multiple masters sharing a drm device in order to get fast-user-switching to work. It splits out the information associated with the drm master into a separate kref counted structure, and allocates this when a master opens the device node. It also allows the current master to abdicate (say while VT switched), and a new master to take over the hardware. It moves the Intel and radeon drivers to using the sarea from within the new master structures. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c81
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h10
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c30
-rw-r--r--drivers/gpu/drm/i915/i915_mem.c3
5 files changed, 77 insertions, 49 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index afa8a12cd009..dacdf3c577cb 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -39,6 +39,7 @@
39int i915_wait_ring(struct drm_device * dev, int n, const char *caller) 39int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
40{ 40{
41 drm_i915_private_t *dev_priv = dev->dev_private; 41 drm_i915_private_t *dev_priv = dev->dev_private;
42 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
42 drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 43 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
43 u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; 44 u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
44 u32 last_acthd = I915_READ(acthd_reg); 45 u32 last_acthd = I915_READ(acthd_reg);
@@ -55,8 +56,8 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
55 if (ring->space >= n) 56 if (ring->space >= n)
56 return 0; 57 return 0;
57 58
58 if (dev_priv->sarea_priv) 59 if (master_priv->sarea_priv)
59 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 60 master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
60 61
61 if (ring->head != last_head) 62 if (ring->head != last_head)
62 i = 0; 63 i = 0;
@@ -121,6 +122,7 @@ static void i915_free_hws(struct drm_device *dev)
121void i915_kernel_lost_context(struct drm_device * dev) 122void i915_kernel_lost_context(struct drm_device * dev)
122{ 123{
123 drm_i915_private_t *dev_priv = dev->dev_private; 124 drm_i915_private_t *dev_priv = dev->dev_private;
125 struct drm_i915_master_private *master_priv;
124 drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 126 drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
125 127
126 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 128 ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
@@ -129,8 +131,12 @@ void i915_kernel_lost_context(struct drm_device * dev)
129 if (ring->space < 0) 131 if (ring->space < 0)
130 ring->space += ring->Size; 132 ring->space += ring->Size;
131 133
132 if (ring->head == ring->tail && dev_priv->sarea_priv) 134 if (!dev->primary->master)
133 dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; 135 return;
136
137 master_priv = dev->primary->master->driver_priv;
138 if (ring->head == ring->tail && master_priv->sarea_priv)
139 master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
134} 140}
135 141
136static int i915_dma_cleanup(struct drm_device * dev) 142static int i915_dma_cleanup(struct drm_device * dev)
@@ -154,25 +160,13 @@ static int i915_dma_cleanup(struct drm_device * dev)
154 if (I915_NEED_GFX_HWS(dev)) 160 if (I915_NEED_GFX_HWS(dev))
155 i915_free_hws(dev); 161 i915_free_hws(dev);
156 162
157 dev_priv->sarea = NULL;
158 dev_priv->sarea_priv = NULL;
159
160 return 0; 163 return 0;
161} 164}
162 165
163static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) 166static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
164{ 167{
165 drm_i915_private_t *dev_priv = dev->dev_private; 168 drm_i915_private_t *dev_priv = dev->dev_private;
166 169 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
167 dev_priv->sarea = drm_getsarea(dev);
168 if (!dev_priv->sarea) {
169 DRM_ERROR("can not find sarea!\n");
170 i915_dma_cleanup(dev);
171 return -EINVAL;
172 }
173
174 dev_priv->sarea_priv = (drm_i915_sarea_t *)
175 ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
176 170
177 if (init->ring_size != 0) { 171 if (init->ring_size != 0) {
178 if (dev_priv->ring.ring_obj != NULL) { 172 if (dev_priv->ring.ring_obj != NULL) {
@@ -207,7 +201,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
207 dev_priv->back_offset = init->back_offset; 201 dev_priv->back_offset = init->back_offset;
208 dev_priv->front_offset = init->front_offset; 202 dev_priv->front_offset = init->front_offset;
209 dev_priv->current_page = 0; 203 dev_priv->current_page = 0;
210 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; 204 if (master_priv->sarea_priv)
205 master_priv->sarea_priv->pf_current_page = 0;
211 206
212 /* Allow hardware batchbuffers unless told otherwise. 207 /* Allow hardware batchbuffers unless told otherwise.
213 */ 208 */
@@ -222,11 +217,6 @@ static int i915_dma_resume(struct drm_device * dev)
222 217
223 DRM_DEBUG("%s\n", __func__); 218 DRM_DEBUG("%s\n", __func__);
224 219
225 if (!dev_priv->sarea) {
226 DRM_ERROR("can not find sarea!\n");
227 return -EINVAL;
228 }
229
230 if (dev_priv->ring.map.handle == NULL) { 220 if (dev_priv->ring.map.handle == NULL) {
231 DRM_ERROR("can not ioremap virtual address for" 221 DRM_ERROR("can not ioremap virtual address for"
232 " ring buffer\n"); 222 " ring buffer\n");
@@ -435,13 +425,14 @@ i915_emit_box(struct drm_device *dev,
435static void i915_emit_breadcrumb(struct drm_device *dev) 425static void i915_emit_breadcrumb(struct drm_device *dev)
436{ 426{
437 drm_i915_private_t *dev_priv = dev->dev_private; 427 drm_i915_private_t *dev_priv = dev->dev_private;
428 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
438 RING_LOCALS; 429 RING_LOCALS;
439 430
440 dev_priv->counter++; 431 dev_priv->counter++;
441 if (dev_priv->counter > 0x7FFFFFFFUL) 432 if (dev_priv->counter > 0x7FFFFFFFUL)
442 dev_priv->counter = 0; 433 dev_priv->counter = 0;
443 if (dev_priv->sarea_priv) 434 if (master_priv->sarea_priv)
444 dev_priv->sarea_priv->last_enqueue = dev_priv->counter; 435 master_priv->sarea_priv->last_enqueue = dev_priv->counter;
445 436
446 BEGIN_LP_RING(4); 437 BEGIN_LP_RING(4);
447 OUT_RING(MI_STORE_DWORD_INDEX); 438 OUT_RING(MI_STORE_DWORD_INDEX);
@@ -537,15 +528,17 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
537static int i915_dispatch_flip(struct drm_device * dev) 528static int i915_dispatch_flip(struct drm_device * dev)
538{ 529{
539 drm_i915_private_t *dev_priv = dev->dev_private; 530 drm_i915_private_t *dev_priv = dev->dev_private;
531 struct drm_i915_master_private *master_priv =
532 dev->primary->master->driver_priv;
540 RING_LOCALS; 533 RING_LOCALS;
541 534
542 if (!dev_priv->sarea_priv) 535 if (!master_priv->sarea_priv)
543 return -EINVAL; 536 return -EINVAL;
544 537
545 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", 538 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
546 __func__, 539 __func__,
547 dev_priv->current_page, 540 dev_priv->current_page,
548 dev_priv->sarea_priv->pf_current_page); 541 master_priv->sarea_priv->pf_current_page);
549 542
550 i915_kernel_lost_context(dev); 543 i915_kernel_lost_context(dev);
551 544
@@ -572,7 +565,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
572 OUT_RING(0); 565 OUT_RING(0);
573 ADVANCE_LP_RING(); 566 ADVANCE_LP_RING();
574 567
575 dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; 568 master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
576 569
577 BEGIN_LP_RING(4); 570 BEGIN_LP_RING(4);
578 OUT_RING(MI_STORE_DWORD_INDEX); 571 OUT_RING(MI_STORE_DWORD_INDEX);
@@ -581,7 +574,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
581 OUT_RING(0); 574 OUT_RING(0);
582 ADVANCE_LP_RING(); 575 ADVANCE_LP_RING();
583 576
584 dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; 577 master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
585 return 0; 578 return 0;
586} 579}
587 580
@@ -611,8 +604,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
611 struct drm_file *file_priv) 604 struct drm_file *file_priv)
612{ 605{
613 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 606 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
607 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
614 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 608 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
615 dev_priv->sarea_priv; 609 master_priv->sarea_priv;
616 drm_i915_batchbuffer_t *batch = data; 610 drm_i915_batchbuffer_t *batch = data;
617 int ret; 611 int ret;
618 612
@@ -644,8 +638,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
644 struct drm_file *file_priv) 638 struct drm_file *file_priv)
645{ 639{
646 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 640 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
641 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
647 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 642 drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
648 dev_priv->sarea_priv; 643 master_priv->sarea_priv;
649 drm_i915_cmdbuffer_t *cmdbuf = data; 644 drm_i915_cmdbuffer_t *cmdbuf = data;
650 int ret; 645 int ret;
651 646
@@ -802,6 +797,30 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
802 return 0; 797 return 0;
803} 798}
804 799
800int i915_master_create(struct drm_device *dev, struct drm_master *master)
801{
802 struct drm_i915_master_private *master_priv;
803
804 master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
805 if (!master_priv)
806 return -ENOMEM;
807
808 master->driver_priv = master_priv;
809 return 0;
810}
811
812void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
813{
814 struct drm_i915_master_private *master_priv = master->driver_priv;
815
816 if (!master_priv)
817 return;
818
819 drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
820
821 master->driver_priv = NULL;
822}
823
805int i915_driver_load(struct drm_device *dev, unsigned long flags) 824int i915_driver_load(struct drm_device *dev, unsigned long flags)
806{ 825{
807 struct drm_i915_private *dev_priv = dev->dev_private; 826 struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a80ead215282..c91648320a8b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -107,6 +107,8 @@ static struct drm_driver driver = {
107 .reclaim_buffers = drm_core_reclaim_buffers, 107 .reclaim_buffers = drm_core_reclaim_buffers,
108 .get_map_ofs = drm_core_get_map_ofs, 108 .get_map_ofs = drm_core_get_map_ofs,
109 .get_reg_ofs = drm_core_get_reg_ofs, 109 .get_reg_ofs = drm_core_get_reg_ofs,
110 .master_create = i915_master_create,
111 .master_destroy = i915_master_destroy,
110 .proc_init = i915_gem_proc_init, 112 .proc_init = i915_gem_proc_init,
111 .proc_cleanup = i915_gem_proc_cleanup, 113 .proc_cleanup = i915_gem_proc_cleanup,
112 .gem_init_object = i915_gem_init_object, 114 .gem_init_object = i915_gem_init_object,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b3cc4731aa7c..ba096f9a7641 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -103,15 +103,18 @@ struct intel_opregion {
103 int enabled; 103 int enabled;
104}; 104};
105 105
106struct drm_i915_master_private {
107 drm_local_map_t *sarea;
108 struct _drm_i915_sarea *sarea_priv;
109};
110
106typedef struct drm_i915_private { 111typedef struct drm_i915_private {
107 struct drm_device *dev; 112 struct drm_device *dev;
108 113
109 int has_gem; 114 int has_gem;
110 115
111 void __iomem *regs; 116 void __iomem *regs;
112 drm_local_map_t *sarea;
113 117
114 drm_i915_sarea_t *sarea_priv;
115 drm_i915_ring_buffer_t ring; 118 drm_i915_ring_buffer_t ring;
116 119
117 drm_dma_handle_t *status_page_dmah; 120 drm_dma_handle_t *status_page_dmah;
@@ -417,6 +420,9 @@ struct drm_i915_file_private {
417extern struct drm_ioctl_desc i915_ioctls[]; 420extern struct drm_ioctl_desc i915_ioctls[];
418extern int i915_max_ioctl; 421extern int i915_max_ioctl;
419 422
423extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
424extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
425
420 /* i915_dma.c */ 426 /* i915_dma.c */
421extern void i915_kernel_lost_context(struct drm_device * dev); 427extern void i915_kernel_lost_context(struct drm_device * dev);
422extern int i915_driver_load(struct drm_device *, unsigned long flags); 428extern int i915_driver_load(struct drm_device *, unsigned long flags);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 69b9a42da95e..9b673d2f912b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -168,6 +168,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
168{ 168{
169 struct drm_device *dev = (struct drm_device *) arg; 169 struct drm_device *dev = (struct drm_device *) arg;
170 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 170 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
171 struct drm_i915_master_private *master_priv;
171 u32 iir, new_iir; 172 u32 iir, new_iir;
172 u32 pipea_stats, pipeb_stats; 173 u32 pipea_stats, pipeb_stats;
173 u32 vblank_status; 174 u32 vblank_status;
@@ -222,9 +223,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
222 I915_WRITE(IIR, iir); 223 I915_WRITE(IIR, iir);
223 new_iir = I915_READ(IIR); /* Flush posted writes */ 224 new_iir = I915_READ(IIR); /* Flush posted writes */
224 225
225 if (dev_priv->sarea_priv) 226 if (dev->primary->master) {
226 dev_priv->sarea_priv->last_dispatch = 227 master_priv = dev->primary->master->driver_priv;
227 READ_BREADCRUMB(dev_priv); 228 if (master_priv->sarea_priv)
229 master_priv->sarea_priv->last_dispatch =
230 READ_BREADCRUMB(dev_priv);
231 }
228 232
229 if (iir & I915_USER_INTERRUPT) { 233 if (iir & I915_USER_INTERRUPT) {
230 dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); 234 dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
@@ -269,6 +273,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
269static int i915_emit_irq(struct drm_device * dev) 273static int i915_emit_irq(struct drm_device * dev)
270{ 274{
271 drm_i915_private_t *dev_priv = dev->dev_private; 275 drm_i915_private_t *dev_priv = dev->dev_private;
276 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
272 RING_LOCALS; 277 RING_LOCALS;
273 278
274 i915_kernel_lost_context(dev); 279 i915_kernel_lost_context(dev);
@@ -278,8 +283,8 @@ static int i915_emit_irq(struct drm_device * dev)
278 dev_priv->counter++; 283 dev_priv->counter++;
279 if (dev_priv->counter > 0x7FFFFFFFUL) 284 if (dev_priv->counter > 0x7FFFFFFFUL)
280 dev_priv->counter = 1; 285 dev_priv->counter = 1;
281 if (dev_priv->sarea_priv) 286 if (master_priv->sarea_priv)
282 dev_priv->sarea_priv->last_enqueue = dev_priv->counter; 287 master_priv->sarea_priv->last_enqueue = dev_priv->counter;
283 288
284 BEGIN_LP_RING(4); 289 BEGIN_LP_RING(4);
285 OUT_RING(MI_STORE_DWORD_INDEX); 290 OUT_RING(MI_STORE_DWORD_INDEX);
@@ -317,21 +322,20 @@ void i915_user_irq_put(struct drm_device *dev)
317static int i915_wait_irq(struct drm_device * dev, int irq_nr) 322static int i915_wait_irq(struct drm_device * dev, int irq_nr)
318{ 323{
319 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 324 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
325 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
320 int ret = 0; 326 int ret = 0;
321 327
322 DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr, 328 DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
323 READ_BREADCRUMB(dev_priv)); 329 READ_BREADCRUMB(dev_priv));
324 330
325 if (READ_BREADCRUMB(dev_priv) >= irq_nr) { 331 if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
326 if (dev_priv->sarea_priv) { 332 if (master_priv->sarea_priv)
327 dev_priv->sarea_priv->last_dispatch = 333 master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
328 READ_BREADCRUMB(dev_priv);
329 }
330 return 0; 334 return 0;
331 } 335 }
332 336
333 if (dev_priv->sarea_priv) 337 if (master_priv->sarea_priv)
334 dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 338 master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
335 339
336 i915_user_irq_get(dev); 340 i915_user_irq_get(dev);
337 DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, 341 DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
@@ -343,10 +347,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
343 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); 347 READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
344 } 348 }
345 349
346 if (dev_priv->sarea_priv)
347 dev_priv->sarea_priv->last_dispatch =
348 READ_BREADCRUMB(dev_priv);
349
350 return ret; 350 return ret;
351} 351}
352 352
diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c
index 6126a60dc9cb..96e271986d2a 100644
--- a/drivers/gpu/drm/i915/i915_mem.c
+++ b/drivers/gpu/drm/i915/i915_mem.c
@@ -46,7 +46,8 @@
46static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use) 46static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
47{ 47{
48 drm_i915_private_t *dev_priv = dev->dev_private; 48 drm_i915_private_t *dev_priv = dev->dev_private;
49 drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; 49 struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
50 drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv;
50 struct drm_tex_region *list; 51 struct drm_tex_region *list;
51 unsigned shift, nr; 52 unsigned shift, nr;
52 unsigned start; 53 unsigned start;