Rev 2997 | Rev 5078 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2997 | Rev 3764 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright 2011 Christian König. |
2 | * Copyright 2011 Christian König. |
3 | * All Rights Reserved. |
3 | * All Rights Reserved. |
4 | * |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the |
6 | * copy of this software and associated documentation files (the |
7 | * "Software"), to deal in the Software without restriction, including |
7 | * "Software"), to deal in the Software without restriction, including |
8 | * without limitation the rights to use, copy, modify, merge, publish, |
8 | * without limitation the rights to use, copy, modify, merge, publish, |
9 | * distribute, sub license, and/or sell copies of the Software, and to |
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 |
10 | * permit persons to whom the Software is furnished to do so, subject to |
11 | * the following conditions: |
11 | * the following conditions: |
12 | * |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
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, |
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
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, |
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 |
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 |
18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
20 | * |
20 | * |
21 | * The above copyright notice and this permission notice (including the |
21 | * The above copyright notice and this permission notice (including the |
22 | * next paragraph) shall be included in all copies or substantial portions |
22 | * next paragraph) shall be included in all copies or substantial portions |
23 | * of the Software. |
23 | * of the Software. |
24 | * |
24 | * |
25 | */ |
25 | */ |
26 | /* |
26 | /* |
27 | * Authors: |
27 | * Authors: |
28 | * Christian König |
28 | * Christian König |
29 | */ |
29 | */ |
30 | #include |
30 | #include |
31 | #include "radeon.h" |
31 | #include "radeon.h" |
32 | 32 | ||
33 | 33 | ||
34 | int radeon_semaphore_create(struct radeon_device *rdev, |
34 | int radeon_semaphore_create(struct radeon_device *rdev, |
35 | struct radeon_semaphore **semaphore) |
35 | struct radeon_semaphore **semaphore) |
36 | { |
36 | { |
37 | int r; |
37 | int r; |
38 | 38 | ||
39 | *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); |
39 | *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); |
40 | if (*semaphore == NULL) { |
40 | if (*semaphore == NULL) { |
41 | return -ENOMEM; |
41 | return -ENOMEM; |
42 | } |
42 | } |
43 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, |
43 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, |
44 | &(*semaphore)->sa_bo, 8, 8, true); |
44 | &(*semaphore)->sa_bo, 8, 8, true); |
45 | if (r) { |
45 | if (r) { |
46 | kfree(*semaphore); |
46 | kfree(*semaphore); |
47 | *semaphore = NULL; |
47 | *semaphore = NULL; |
48 | return r; |
48 | return r; |
49 | } |
49 | } |
50 | (*semaphore)->waiters = 0; |
50 | (*semaphore)->waiters = 0; |
51 | (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); |
51 | (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); |
52 | *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; |
52 | *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; |
53 | return 0; |
53 | return 0; |
54 | } |
54 | } |
55 | 55 | ||
56 | void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, |
56 | void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, |
57 | struct radeon_semaphore *semaphore) |
57 | struct radeon_semaphore *semaphore) |
58 | { |
58 | { |
59 | --semaphore->waiters; |
59 | --semaphore->waiters; |
60 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false); |
60 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false); |
61 | } |
61 | } |
62 | 62 | ||
63 | void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, |
63 | void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, |
64 | struct radeon_semaphore *semaphore) |
64 | struct radeon_semaphore *semaphore) |
65 | { |
65 | { |
66 | ++semaphore->waiters; |
66 | ++semaphore->waiters; |
67 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); |
67 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); |
68 | } |
68 | } |
69 | 69 | ||
70 | /* caller must hold ring lock */ |
70 | /* caller must hold ring lock */ |
71 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
71 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
72 | struct radeon_semaphore *semaphore, |
72 | struct radeon_semaphore *semaphore, |
73 | int signaler, int waiter) |
73 | int signaler, int waiter) |
74 | { |
74 | { |
75 | int r; |
75 | int r; |
76 | 76 | ||
77 | /* no need to signal and wait on the same ring */ |
77 | /* no need to signal and wait on the same ring */ |
78 | if (signaler == waiter) { |
78 | if (signaler == waiter) { |
79 | return 0; |
79 | return 0; |
80 | } |
80 | } |
81 | 81 | ||
82 | /* prevent GPU deadlocks */ |
82 | /* prevent GPU deadlocks */ |
83 | if (!rdev->ring[signaler].ready) { |
83 | if (!rdev->ring[signaler].ready) { |
84 | dev_err(rdev->dev, "Trying to sync to a disabled ring!"); |
84 | dev_err(rdev->dev, "Trying to sync to a disabled ring!"); |
85 | return -EINVAL; |
85 | return -EINVAL; |
86 | } |
86 | } |
87 | 87 | ||
88 | r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); |
88 | r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); |
89 | if (r) { |
89 | if (r) { |
90 | return r; |
90 | return r; |
91 | } |
91 | } |
92 | radeon_semaphore_emit_signal(rdev, signaler, semaphore); |
92 | radeon_semaphore_emit_signal(rdev, signaler, semaphore); |
93 | radeon_ring_commit(rdev, &rdev->ring[signaler]); |
93 | radeon_ring_commit(rdev, &rdev->ring[signaler]); |
94 | 94 | ||
95 | /* we assume caller has already allocated space on waiters ring */ |
95 | /* we assume caller has already allocated space on waiters ring */ |
96 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); |
96 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); |
- | 97 | ||
- | 98 | /* for debugging lockup only, used by sysfs debug files */ |
|
- | 99 | rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; |
|
- | 100 | rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; |
|
97 | 101 | ||
98 | return 0; |
102 | return 0; |
99 | } |
103 | } |
100 | 104 | ||
101 | void radeon_semaphore_free(struct radeon_device *rdev, |
105 | void radeon_semaphore_free(struct radeon_device *rdev, |
102 | struct radeon_semaphore **semaphore, |
106 | struct radeon_semaphore **semaphore, |
103 | struct radeon_fence *fence) |
107 | struct radeon_fence *fence) |
104 | { |
108 | { |
105 | if (semaphore == NULL || *semaphore == NULL) { |
109 | if (semaphore == NULL || *semaphore == NULL) { |
106 | return; |
110 | return; |
107 | } |
111 | } |
108 | if ((*semaphore)->waiters > 0) { |
112 | if ((*semaphore)->waiters > 0) { |
109 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," |
113 | dev_err(rdev->dev, "semaphore %p has more waiters than signalers," |
110 | " hardware lockup imminent!\n", *semaphore); |
114 | " hardware lockup imminent!\n", *semaphore); |
111 | } |
115 | } |
112 | radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); |
116 | radeon_sa_bo_free(rdev, &(*semaphore)->sa_bo, fence); |
113 | kfree(*semaphore); |
117 | kfree(*semaphore); |
114 | *semaphore = NULL; |
118 | *semaphore = NULL; |
115 | } |
119 | } |