2 * Copyright 2011 Christian König.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 * The above copyright notice and this permission notice (including the
22 * next paragraph) shall be included in all copies or substantial portions
28 * Christian König <deathsimple@vodafone.de>
34 static int radeon_semaphore_add_bo(struct radeon_device
*rdev
)
36 struct radeon_semaphore_bo
*bo
;
37 unsigned long irq_flags
;
43 bo
= kmalloc(sizeof(struct radeon_semaphore_bo
), GFP_KERNEL
);
47 INIT_LIST_HEAD(&bo
->free
);
48 INIT_LIST_HEAD(&bo
->list
);
51 r
= radeon_ib_get(rdev
, 0, &bo
->ib
, RADEON_SEMAPHORE_BO_SIZE
);
53 dev_err(rdev
->dev
, "failed to get a bo after 5 retry\n");
57 gpu_addr
= rdev
->ib_pool
.sa_manager
.gpu_addr
;
58 gpu_addr
+= bo
->ib
->sa_bo
.offset
;
59 cpu_ptr
= rdev
->ib_pool
.sa_manager
.cpu_ptr
;
60 cpu_ptr
+= (bo
->ib
->sa_bo
.offset
>> 2);
61 for (i
= 0; i
< (RADEON_SEMAPHORE_BO_SIZE
/8); i
++) {
62 bo
->semaphores
[i
].gpu_addr
= gpu_addr
;
63 bo
->semaphores
[i
].cpu_ptr
= cpu_ptr
;
64 bo
->semaphores
[i
].bo
= bo
;
65 list_add_tail(&bo
->semaphores
[i
].list
, &bo
->free
);
69 write_lock_irqsave(&rdev
->semaphore_drv
.lock
, irq_flags
);
70 list_add_tail(&bo
->list
, &rdev
->semaphore_drv
.bo
);
71 write_unlock_irqrestore(&rdev
->semaphore_drv
.lock
, irq_flags
);
75 static void radeon_semaphore_del_bo_locked(struct radeon_device
*rdev
,
76 struct radeon_semaphore_bo
*bo
)
78 radeon_sa_bo_free(rdev
, &bo
->ib
->sa_bo
);
79 radeon_fence_unref(&bo
->ib
->fence
);
84 void radeon_semaphore_shrink_locked(struct radeon_device
*rdev
)
86 struct radeon_semaphore_bo
*bo
, *n
;
88 if (list_empty(&rdev
->semaphore_drv
.bo
)) {
91 /* only shrink if first bo has free semaphore */
92 bo
= list_first_entry(&rdev
->semaphore_drv
.bo
, struct radeon_semaphore_bo
, list
);
93 if (list_empty(&bo
->free
)) {
96 list_for_each_entry_safe_continue(bo
, n
, &rdev
->semaphore_drv
.bo
, list
) {
99 radeon_semaphore_del_bo_locked(rdev
, bo
);
103 int radeon_semaphore_create(struct radeon_device
*rdev
,
104 struct radeon_semaphore
**semaphore
)
106 struct radeon_semaphore_bo
*bo
;
107 unsigned long irq_flags
;
108 bool do_retry
= true;
113 write_lock_irqsave(&rdev
->semaphore_drv
.lock
, irq_flags
);
114 list_for_each_entry(bo
, &rdev
->semaphore_drv
.bo
, list
) {
115 if (list_empty(&bo
->free
))
117 *semaphore
= list_first_entry(&bo
->free
, struct radeon_semaphore
, list
);
118 (*semaphore
)->cpu_ptr
[0] = 0;
119 (*semaphore
)->cpu_ptr
[1] = 0;
120 list_del(&(*semaphore
)->list
);
124 write_unlock_irqrestore(&rdev
->semaphore_drv
.lock
, irq_flags
);
126 if (*semaphore
== NULL
) {
129 r
= radeon_semaphore_add_bo(rdev
);
140 void radeon_semaphore_emit_signal(struct radeon_device
*rdev
, int ring
,
141 struct radeon_semaphore
*semaphore
)
143 radeon_semaphore_ring_emit(rdev
, ring
, &rdev
->ring
[ring
], semaphore
, false);
146 void radeon_semaphore_emit_wait(struct radeon_device
*rdev
, int ring
,
147 struct radeon_semaphore
*semaphore
)
149 radeon_semaphore_ring_emit(rdev
, ring
, &rdev
->ring
[ring
], semaphore
, true);
152 void radeon_semaphore_free(struct radeon_device
*rdev
,
153 struct radeon_semaphore
*semaphore
)
155 unsigned long irq_flags
;
157 write_lock_irqsave(&rdev
->semaphore_drv
.lock
, irq_flags
);
158 semaphore
->bo
->nused
--;
159 list_add_tail(&semaphore
->list
, &semaphore
->bo
->free
);
160 radeon_semaphore_shrink_locked(rdev
);
161 write_unlock_irqrestore(&rdev
->semaphore_drv
.lock
, irq_flags
);
164 void radeon_semaphore_driver_fini(struct radeon_device
*rdev
)
166 struct radeon_semaphore_bo
*bo
, *n
;
167 unsigned long irq_flags
;
169 write_lock_irqsave(&rdev
->semaphore_drv
.lock
, irq_flags
);
170 /* we force to free everything */
171 list_for_each_entry_safe(bo
, n
, &rdev
->semaphore_drv
.bo
, list
) {
172 if (!list_empty(&bo
->free
)) {
173 dev_err(rdev
->dev
, "still in use semaphore\n");
175 radeon_semaphore_del_bo_locked(rdev
, bo
);
177 write_unlock_irqrestore(&rdev
->semaphore_drv
.lock
, irq_flags
);