diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 104 |
1 files changed, 97 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 5ce65280b396..a98fbbb4739f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | |||
| @@ -136,7 +136,8 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring) | |||
| 136 | if (ring->funcs->end_use) | 136 | if (ring->funcs->end_use) |
| 137 | ring->funcs->end_use(ring); | 137 | ring->funcs->end_use(ring); |
| 138 | 138 | ||
| 139 | amdgpu_ring_lru_touch(ring->adev, ring); | 139 | if (ring->funcs->type != AMDGPU_RING_TYPE_KIQ) |
| 140 | amdgpu_ring_lru_touch(ring->adev, ring); | ||
| 140 | } | 141 | } |
| 141 | 142 | ||
| 142 | /** | 143 | /** |
| @@ -155,6 +156,75 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring) | |||
| 155 | } | 156 | } |
| 156 | 157 | ||
| 157 | /** | 158 | /** |
| 159 | * amdgpu_ring_priority_put - restore a ring's priority | ||
| 160 | * | ||
| 161 | * @ring: amdgpu_ring structure holding the information | ||
| 162 | * @priority: target priority | ||
| 163 | * | ||
| 164 | * Release a request for executing at @priority | ||
| 165 | */ | ||
| 166 | void amdgpu_ring_priority_put(struct amdgpu_ring *ring, | ||
| 167 | enum amd_sched_priority priority) | ||
| 168 | { | ||
| 169 | int i; | ||
| 170 | |||
| 171 | if (!ring->funcs->set_priority) | ||
| 172 | return; | ||
| 173 | |||
| 174 | if (atomic_dec_return(&ring->num_jobs[priority]) > 0) | ||
| 175 | return; | ||
| 176 | |||
| 177 | /* no need to restore if the job is already at the lowest priority */ | ||
| 178 | if (priority == AMD_SCHED_PRIORITY_NORMAL) | ||
| 179 | return; | ||
| 180 | |||
| 181 | mutex_lock(&ring->priority_mutex); | ||
| 182 | /* something higher prio is executing, no need to decay */ | ||
| 183 | if (ring->priority > priority) | ||
| 184 | goto out_unlock; | ||
| 185 | |||
| 186 | /* decay priority to the next level with a job available */ | ||
| 187 | for (i = priority; i >= AMD_SCHED_PRIORITY_MIN; i--) { | ||
| 188 | if (i == AMD_SCHED_PRIORITY_NORMAL | ||
| 189 | || atomic_read(&ring->num_jobs[i])) { | ||
| 190 | ring->priority = i; | ||
| 191 | ring->funcs->set_priority(ring, i); | ||
| 192 | break; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | out_unlock: | ||
| 197 | mutex_unlock(&ring->priority_mutex); | ||
| 198 | } | ||
| 199 | |||
| 200 | /** | ||
| 201 | * amdgpu_ring_priority_get - change the ring's priority | ||
| 202 | * | ||
| 203 | * @ring: amdgpu_ring structure holding the information | ||
| 204 | * @priority: target priority | ||
| 205 | * | ||
| 206 | * Request a ring's priority to be raised to @priority (refcounted). | ||
| 207 | */ | ||
| 208 | void amdgpu_ring_priority_get(struct amdgpu_ring *ring, | ||
| 209 | enum amd_sched_priority priority) | ||
| 210 | { | ||
| 211 | if (!ring->funcs->set_priority) | ||
| 212 | return; | ||
| 213 | |||
| 214 | atomic_inc(&ring->num_jobs[priority]); | ||
| 215 | |||
| 216 | mutex_lock(&ring->priority_mutex); | ||
| 217 | if (priority <= ring->priority) | ||
| 218 | goto out_unlock; | ||
| 219 | |||
| 220 | ring->priority = priority; | ||
| 221 | ring->funcs->set_priority(ring, priority); | ||
| 222 | |||
| 223 | out_unlock: | ||
| 224 | mutex_unlock(&ring->priority_mutex); | ||
| 225 | } | ||
| 226 | |||
| 227 | /** | ||
| 158 | * amdgpu_ring_init - init driver ring struct. | 228 | * amdgpu_ring_init - init driver ring struct. |
| 159 | * | 229 | * |
| 160 | * @adev: amdgpu_device pointer | 230 | * @adev: amdgpu_device pointer |
| @@ -169,7 +239,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, | |||
| 169 | unsigned max_dw, struct amdgpu_irq_src *irq_src, | 239 | unsigned max_dw, struct amdgpu_irq_src *irq_src, |
| 170 | unsigned irq_type) | 240 | unsigned irq_type) |
| 171 | { | 241 | { |
| 172 | int r; | 242 | int r, i; |
| 173 | int sched_hw_submission = amdgpu_sched_hw_submission; | 243 | int sched_hw_submission = amdgpu_sched_hw_submission; |
| 174 | 244 | ||
| 175 | /* Set the hw submission limit higher for KIQ because | 245 | /* Set the hw submission limit higher for KIQ because |
| @@ -247,9 +317,14 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, | |||
| 247 | } | 317 | } |
| 248 | 318 | ||
| 249 | ring->max_dw = max_dw; | 319 | ring->max_dw = max_dw; |
| 320 | ring->priority = AMD_SCHED_PRIORITY_NORMAL; | ||
| 321 | mutex_init(&ring->priority_mutex); | ||
| 250 | INIT_LIST_HEAD(&ring->lru_list); | 322 | INIT_LIST_HEAD(&ring->lru_list); |
| 251 | amdgpu_ring_lru_touch(adev, ring); | 323 | amdgpu_ring_lru_touch(adev, ring); |
| 252 | 324 | ||
| 325 | for (i = 0; i < AMD_SCHED_PRIORITY_MAX; ++i) | ||
| 326 | atomic_set(&ring->num_jobs[i], 0); | ||
| 327 | |||
| 253 | if (amdgpu_debugfs_ring_init(adev, ring)) { | 328 | if (amdgpu_debugfs_ring_init(adev, ring)) { |
| 254 | DRM_ERROR("Failed to register debugfs file for rings !\n"); | 329 | DRM_ERROR("Failed to register debugfs file for rings !\n"); |
| 255 | } | 330 | } |
| @@ -315,14 +390,16 @@ static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring, | |||
| 315 | * @type: amdgpu_ring_type enum | 390 | * @type: amdgpu_ring_type enum |
| 316 | * @blacklist: blacklisted ring ids array | 391 | * @blacklist: blacklisted ring ids array |
| 317 | * @num_blacklist: number of entries in @blacklist | 392 | * @num_blacklist: number of entries in @blacklist |
| 393 | * @lru_pipe_order: find a ring from the least recently used pipe | ||
| 318 | * @ring: output ring | 394 | * @ring: output ring |
| 319 | * | 395 | * |
| 320 | * Retrieve the amdgpu_ring structure for the least recently used ring of | 396 | * Retrieve the amdgpu_ring structure for the least recently used ring of |
| 321 | * a specific IP block (all asics). | 397 | * a specific IP block (all asics). |
| 322 | * Returns 0 on success, error on failure. | 398 | * Returns 0 on success, error on failure. |
| 323 | */ | 399 | */ |
| 324 | int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, | 400 | int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, |
| 325 | int num_blacklist, struct amdgpu_ring **ring) | 401 | int *blacklist, int num_blacklist, |
| 402 | bool lru_pipe_order, struct amdgpu_ring **ring) | ||
| 326 | { | 403 | { |
| 327 | struct amdgpu_ring *entry; | 404 | struct amdgpu_ring *entry; |
| 328 | 405 | ||
| @@ -337,10 +414,23 @@ int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, | |||
| 337 | if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist)) | 414 | if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist)) |
| 338 | continue; | 415 | continue; |
| 339 | 416 | ||
| 340 | *ring = entry; | 417 | if (!*ring) { |
| 341 | amdgpu_ring_lru_touch_locked(adev, *ring); | 418 | *ring = entry; |
| 342 | break; | 419 | |
| 420 | /* We are done for ring LRU */ | ||
| 421 | if (!lru_pipe_order) | ||
| 422 | break; | ||
| 423 | } | ||
| 424 | |||
| 425 | /* Move all rings on the same pipe to the end of the list */ | ||
| 426 | if (entry->pipe == (*ring)->pipe) | ||
| 427 | amdgpu_ring_lru_touch_locked(adev, entry); | ||
| 343 | } | 428 | } |
| 429 | |||
| 430 | /* Move the ring we found to the end of the list */ | ||
| 431 | if (*ring) | ||
| 432 | amdgpu_ring_lru_touch_locked(adev, *ring); | ||
| 433 | |||
| 344 | spin_unlock(&adev->ring_lru_list_lock); | 434 | spin_unlock(&adev->ring_lru_list_lock); |
| 345 | 435 | ||
| 346 | if (!*ring) { | 436 | if (!*ring) { |
