.. | .. |
---|
33 | 33 | #include "kfd_mqd_manager.h" |
---|
34 | 34 | #include "cik_regs.h" |
---|
35 | 35 | #include "kfd_kernel_queue.h" |
---|
| 36 | +#include "amdgpu_amdkfd.h" |
---|
36 | 37 | |
---|
37 | 38 | /* Size of the per-pipe EOP queue */ |
---|
38 | 39 | #define CIK_HPD_EOP_BYTES_LOG2 11 |
---|
39 | 40 | #define CIK_HPD_EOP_BYTES (1U << CIK_HPD_EOP_BYTES_LOG2) |
---|
40 | 41 | |
---|
41 | 42 | static int set_pasid_vmid_mapping(struct device_queue_manager *dqm, |
---|
42 | | - unsigned int pasid, unsigned int vmid); |
---|
43 | | - |
---|
44 | | -static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, |
---|
45 | | - struct queue *q, |
---|
46 | | - struct qcm_process_device *qpd); |
---|
| 43 | + u32 pasid, unsigned int vmid); |
---|
47 | 44 | |
---|
48 | 45 | static int execute_queues_cpsch(struct device_queue_manager *dqm, |
---|
49 | 46 | enum kfd_unmap_queues_filter filter, |
---|
.. | .. |
---|
54 | 51 | |
---|
55 | 52 | static int map_queues_cpsch(struct device_queue_manager *dqm); |
---|
56 | 53 | |
---|
57 | | -static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm, |
---|
58 | | - struct queue *q, |
---|
59 | | - struct qcm_process_device *qpd); |
---|
60 | | - |
---|
61 | 54 | static void deallocate_sdma_queue(struct device_queue_manager *dqm, |
---|
62 | | - unsigned int sdma_queue_id); |
---|
| 55 | + struct queue *q); |
---|
63 | 56 | |
---|
| 57 | +static inline void deallocate_hqd(struct device_queue_manager *dqm, |
---|
| 58 | + struct queue *q); |
---|
| 59 | +static int allocate_hqd(struct device_queue_manager *dqm, struct queue *q); |
---|
| 60 | +static int allocate_sdma_queue(struct device_queue_manager *dqm, |
---|
| 61 | + struct queue *q); |
---|
64 | 62 | static void kfd_process_hw_exception(struct work_struct *work); |
---|
65 | 63 | |
---|
66 | 64 | static inline |
---|
67 | 65 | enum KFD_MQD_TYPE get_mqd_type_from_queue_type(enum kfd_queue_type type) |
---|
68 | 66 | { |
---|
69 | | - if (type == KFD_QUEUE_TYPE_SDMA) |
---|
| 67 | + if (type == KFD_QUEUE_TYPE_SDMA || type == KFD_QUEUE_TYPE_SDMA_XGMI) |
---|
70 | 68 | return KFD_MQD_TYPE_SDMA; |
---|
71 | 69 | return KFD_MQD_TYPE_CP; |
---|
72 | 70 | } |
---|
.. | .. |
---|
80 | 78 | /* queue is available for KFD usage if bit is 1 */ |
---|
81 | 79 | for (i = 0; i < dqm->dev->shared_resources.num_queue_per_pipe; ++i) |
---|
82 | 80 | if (test_bit(pipe_offset + i, |
---|
83 | | - dqm->dev->shared_resources.queue_bitmap)) |
---|
| 81 | + dqm->dev->shared_resources.cp_queue_bitmap)) |
---|
84 | 82 | return true; |
---|
85 | 83 | return false; |
---|
86 | 84 | } |
---|
87 | 85 | |
---|
88 | | -unsigned int get_queues_num(struct device_queue_manager *dqm) |
---|
| 86 | +unsigned int get_cp_queues_num(struct device_queue_manager *dqm) |
---|
89 | 87 | { |
---|
90 | | - return bitmap_weight(dqm->dev->shared_resources.queue_bitmap, |
---|
| 88 | + return bitmap_weight(dqm->dev->shared_resources.cp_queue_bitmap, |
---|
91 | 89 | KGD_MAX_QUEUES); |
---|
92 | 90 | } |
---|
93 | 91 | |
---|
.. | .. |
---|
106 | 104 | return dqm->dev->device_info->num_sdma_engines; |
---|
107 | 105 | } |
---|
108 | 106 | |
---|
| 107 | +static unsigned int get_num_xgmi_sdma_engines(struct device_queue_manager *dqm) |
---|
| 108 | +{ |
---|
| 109 | + return dqm->dev->device_info->num_xgmi_sdma_engines; |
---|
| 110 | +} |
---|
| 111 | + |
---|
| 112 | +static unsigned int get_num_all_sdma_engines(struct device_queue_manager *dqm) |
---|
| 113 | +{ |
---|
| 114 | + return get_num_sdma_engines(dqm) + get_num_xgmi_sdma_engines(dqm); |
---|
| 115 | +} |
---|
| 116 | + |
---|
109 | 117 | unsigned int get_num_sdma_queues(struct device_queue_manager *dqm) |
---|
110 | 118 | { |
---|
111 | 119 | return dqm->dev->device_info->num_sdma_engines |
---|
112 | | - * KFD_SDMA_QUEUES_PER_ENGINE; |
---|
| 120 | + * dqm->dev->device_info->num_sdma_queues_per_engine; |
---|
| 121 | +} |
---|
| 122 | + |
---|
| 123 | +unsigned int get_num_xgmi_sdma_queues(struct device_queue_manager *dqm) |
---|
| 124 | +{ |
---|
| 125 | + return dqm->dev->device_info->num_xgmi_sdma_engines |
---|
| 126 | + * dqm->dev->device_info->num_sdma_queues_per_engine; |
---|
113 | 127 | } |
---|
114 | 128 | |
---|
115 | 129 | void program_sh_mem_settings(struct device_queue_manager *dqm, |
---|
.. | .. |
---|
123 | 137 | qpd->sh_mem_bases); |
---|
124 | 138 | } |
---|
125 | 139 | |
---|
| 140 | +static void increment_queue_count(struct device_queue_manager *dqm, |
---|
| 141 | + struct qcm_process_device *qpd, |
---|
| 142 | + struct queue *q) |
---|
| 143 | +{ |
---|
| 144 | + dqm->active_queue_count++; |
---|
| 145 | + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || |
---|
| 146 | + q->properties.type == KFD_QUEUE_TYPE_DIQ) |
---|
| 147 | + dqm->active_cp_queue_count++; |
---|
| 148 | + |
---|
| 149 | + if (q->properties.is_gws) { |
---|
| 150 | + dqm->gws_queue_count++; |
---|
| 151 | + qpd->mapped_gws_queue = true; |
---|
| 152 | + } |
---|
| 153 | +} |
---|
| 154 | + |
---|
| 155 | +static void decrement_queue_count(struct device_queue_manager *dqm, |
---|
| 156 | + struct qcm_process_device *qpd, |
---|
| 157 | + struct queue *q) |
---|
| 158 | +{ |
---|
| 159 | + dqm->active_queue_count--; |
---|
| 160 | + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || |
---|
| 161 | + q->properties.type == KFD_QUEUE_TYPE_DIQ) |
---|
| 162 | + dqm->active_cp_queue_count--; |
---|
| 163 | + |
---|
| 164 | + if (q->properties.is_gws) { |
---|
| 165 | + dqm->gws_queue_count--; |
---|
| 166 | + qpd->mapped_gws_queue = false; |
---|
| 167 | + } |
---|
| 168 | +} |
---|
| 169 | + |
---|
126 | 170 | static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) |
---|
127 | 171 | { |
---|
128 | 172 | struct kfd_dev *dev = qpd->dqm->dev; |
---|
.. | .. |
---|
132 | 176 | * preserve the user mode ABI. |
---|
133 | 177 | */ |
---|
134 | 178 | q->doorbell_id = q->properties.queue_id; |
---|
135 | | - } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { |
---|
136 | | - /* For SDMA queues on SOC15, use static doorbell |
---|
137 | | - * assignments based on the engine and queue. |
---|
| 179 | + } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 180 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { |
---|
| 181 | + /* For SDMA queues on SOC15 with 8-byte doorbell, use static |
---|
| 182 | + * doorbell assignments based on the engine and queue id. |
---|
| 183 | + * The doobell index distance between RLC (2*i) and (2*i+1) |
---|
| 184 | + * for a SDMA engine is 512. |
---|
138 | 185 | */ |
---|
139 | | - q->doorbell_id = dev->shared_resources.sdma_doorbell |
---|
140 | | - [q->properties.sdma_engine_id] |
---|
141 | | - [q->properties.sdma_queue_id]; |
---|
| 186 | + uint32_t *idx_offset = |
---|
| 187 | + dev->shared_resources.sdma_doorbell_idx; |
---|
| 188 | + |
---|
| 189 | + q->doorbell_id = idx_offset[q->properties.sdma_engine_id] |
---|
| 190 | + + (q->properties.sdma_queue_id & 1) |
---|
| 191 | + * KFD_QUEUE_DOORBELL_MIRROR_OFFSET |
---|
| 192 | + + (q->properties.sdma_queue_id >> 1); |
---|
142 | 193 | } else { |
---|
143 | 194 | /* For CP queues on SOC15 reserve a free doorbell ID */ |
---|
144 | 195 | unsigned int found; |
---|
.. | .. |
---|
154 | 205 | } |
---|
155 | 206 | |
---|
156 | 207 | q->properties.doorbell_off = |
---|
157 | | - kfd_doorbell_id_to_offset(dev, q->process, |
---|
| 208 | + kfd_get_doorbell_dw_offset_in_bar(dev, qpd_to_pdd(qpd), |
---|
158 | 209 | q->doorbell_id); |
---|
159 | | - |
---|
160 | 210 | return 0; |
---|
161 | 211 | } |
---|
162 | 212 | |
---|
.. | .. |
---|
167 | 217 | struct kfd_dev *dev = qpd->dqm->dev; |
---|
168 | 218 | |
---|
169 | 219 | if (!KFD_IS_SOC15(dev->device_info->asic_family) || |
---|
170 | | - q->properties.type == KFD_QUEUE_TYPE_SDMA) |
---|
| 220 | + q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 221 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) |
---|
171 | 222 | return; |
---|
172 | 223 | |
---|
173 | 224 | old = test_and_clear_bit(q->doorbell_id, qpd->doorbell_bitmap); |
---|
.. | .. |
---|
178 | 229 | struct qcm_process_device *qpd, |
---|
179 | 230 | struct queue *q) |
---|
180 | 231 | { |
---|
181 | | - int bit, allocated_vmid; |
---|
| 232 | + int allocated_vmid = -1, i; |
---|
182 | 233 | |
---|
183 | | - if (dqm->vmid_bitmap == 0) |
---|
184 | | - return -ENOMEM; |
---|
| 234 | + for (i = dqm->dev->vm_info.first_vmid_kfd; |
---|
| 235 | + i <= dqm->dev->vm_info.last_vmid_kfd; i++) { |
---|
| 236 | + if (!dqm->vmid_pasid[i]) { |
---|
| 237 | + allocated_vmid = i; |
---|
| 238 | + break; |
---|
| 239 | + } |
---|
| 240 | + } |
---|
185 | 241 | |
---|
186 | | - bit = ffs(dqm->vmid_bitmap) - 1; |
---|
187 | | - dqm->vmid_bitmap &= ~(1 << bit); |
---|
| 242 | + if (allocated_vmid < 0) { |
---|
| 243 | + pr_err("no more vmid to allocate\n"); |
---|
| 244 | + return -ENOSPC; |
---|
| 245 | + } |
---|
188 | 246 | |
---|
189 | | - allocated_vmid = bit + dqm->dev->vm_info.first_vmid_kfd; |
---|
190 | | - pr_debug("vmid allocation %d\n", allocated_vmid); |
---|
| 247 | + pr_debug("vmid allocated: %d\n", allocated_vmid); |
---|
| 248 | + |
---|
| 249 | + dqm->vmid_pasid[allocated_vmid] = q->process->pasid; |
---|
| 250 | + |
---|
| 251 | + set_pasid_vmid_mapping(dqm, q->process->pasid, allocated_vmid); |
---|
| 252 | + |
---|
191 | 253 | qpd->vmid = allocated_vmid; |
---|
192 | 254 | q->properties.vmid = allocated_vmid; |
---|
193 | 255 | |
---|
194 | | - set_pasid_vmid_mapping(dqm, q->process->pasid, q->properties.vmid); |
---|
195 | 256 | program_sh_mem_settings(dqm, qpd); |
---|
196 | 257 | |
---|
197 | 258 | /* qpd->page_table_base is set earlier when register_process() |
---|
.. | .. |
---|
202 | 263 | qpd->page_table_base); |
---|
203 | 264 | /* invalidate the VM context after pasid and vmid mapping is set up */ |
---|
204 | 265 | kfd_flush_tlb(qpd_to_pdd(qpd)); |
---|
| 266 | + |
---|
| 267 | + if (dqm->dev->kfd2kgd->set_scratch_backing_va) |
---|
| 268 | + dqm->dev->kfd2kgd->set_scratch_backing_va(dqm->dev->kgd, |
---|
| 269 | + qpd->sh_hidden_private_base, qpd->vmid); |
---|
205 | 270 | |
---|
206 | 271 | return 0; |
---|
207 | 272 | } |
---|
.. | .. |
---|
219 | 284 | if (ret) |
---|
220 | 285 | return ret; |
---|
221 | 286 | |
---|
222 | | - return kdev->kfd2kgd->submit_ib(kdev->kgd, KGD_ENGINE_MEC1, qpd->vmid, |
---|
| 287 | + return amdgpu_amdkfd_submit_ib(kdev->kgd, KGD_ENGINE_MEC1, qpd->vmid, |
---|
223 | 288 | qpd->ib_base, (uint32_t *)qpd->ib_kaddr, |
---|
224 | 289 | pmf->release_mem_size / sizeof(uint32_t)); |
---|
225 | 290 | } |
---|
.. | .. |
---|
228 | 293 | struct qcm_process_device *qpd, |
---|
229 | 294 | struct queue *q) |
---|
230 | 295 | { |
---|
231 | | - int bit = qpd->vmid - dqm->dev->vm_info.first_vmid_kfd; |
---|
232 | | - |
---|
233 | 296 | /* On GFX v7, CP doesn't flush TC at dequeue */ |
---|
234 | 297 | if (q->device->device_info->asic_family == CHIP_HAWAII) |
---|
235 | 298 | if (flush_texture_cache_nocpsch(q->device, qpd)) |
---|
.. | .. |
---|
239 | 302 | |
---|
240 | 303 | /* Release the vmid mapping */ |
---|
241 | 304 | set_pasid_vmid_mapping(dqm, 0, qpd->vmid); |
---|
| 305 | + dqm->vmid_pasid[qpd->vmid] = 0; |
---|
242 | 306 | |
---|
243 | | - dqm->vmid_bitmap |= (1 << bit); |
---|
244 | 307 | qpd->vmid = 0; |
---|
245 | 308 | q->properties.vmid = 0; |
---|
246 | 309 | } |
---|
.. | .. |
---|
249 | 312 | struct queue *q, |
---|
250 | 313 | struct qcm_process_device *qpd) |
---|
251 | 314 | { |
---|
| 315 | + struct mqd_manager *mqd_mgr; |
---|
252 | 316 | int retval; |
---|
253 | | - |
---|
254 | | - print_queue(q); |
---|
255 | 317 | |
---|
256 | 318 | dqm_lock(dqm); |
---|
257 | 319 | |
---|
.. | .. |
---|
269 | 331 | } |
---|
270 | 332 | q->properties.vmid = qpd->vmid; |
---|
271 | 333 | /* |
---|
272 | | - * Eviction state logic: we only mark active queues as evicted |
---|
273 | | - * to avoid the overhead of restoring inactive queues later |
---|
| 334 | + * Eviction state logic: mark all queues as evicted, even ones |
---|
| 335 | + * not currently active. Restoring inactive queues later only |
---|
| 336 | + * updates the is_evicted flag but is a no-op otherwise. |
---|
274 | 337 | */ |
---|
275 | | - if (qpd->evicted) |
---|
276 | | - q->properties.is_evicted = (q->properties.queue_size > 0 && |
---|
277 | | - q->properties.queue_percent > 0 && |
---|
278 | | - q->properties.queue_address != 0); |
---|
| 338 | + q->properties.is_evicted = !!qpd->evicted; |
---|
279 | 339 | |
---|
280 | 340 | q->properties.tba_addr = qpd->tba_addr; |
---|
281 | 341 | q->properties.tma_addr = qpd->tma_addr; |
---|
282 | 342 | |
---|
283 | | - if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) |
---|
284 | | - retval = create_compute_queue_nocpsch(dqm, q, qpd); |
---|
285 | | - else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) |
---|
286 | | - retval = create_sdma_queue_nocpsch(dqm, q, qpd); |
---|
287 | | - else |
---|
288 | | - retval = -EINVAL; |
---|
289 | | - |
---|
290 | | - if (retval) { |
---|
291 | | - if (list_empty(&qpd->queues_list)) |
---|
292 | | - deallocate_vmid(dqm, qpd, q); |
---|
293 | | - goto out_unlock; |
---|
| 343 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 344 | + q->properties.type)]; |
---|
| 345 | + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) { |
---|
| 346 | + retval = allocate_hqd(dqm, q); |
---|
| 347 | + if (retval) |
---|
| 348 | + goto deallocate_vmid; |
---|
| 349 | + pr_debug("Loading mqd to hqd on pipe %d, queue %d\n", |
---|
| 350 | + q->pipe, q->queue); |
---|
| 351 | + } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 352 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { |
---|
| 353 | + retval = allocate_sdma_queue(dqm, q); |
---|
| 354 | + if (retval) |
---|
| 355 | + goto deallocate_vmid; |
---|
| 356 | + dqm->asic_ops.init_sdma_vm(dqm, q, qpd); |
---|
294 | 357 | } |
---|
295 | 358 | |
---|
| 359 | + retval = allocate_doorbell(qpd, q); |
---|
| 360 | + if (retval) |
---|
| 361 | + goto out_deallocate_hqd; |
---|
| 362 | + |
---|
| 363 | + /* Temporarily release dqm lock to avoid a circular lock dependency */ |
---|
| 364 | + dqm_unlock(dqm); |
---|
| 365 | + q->mqd_mem_obj = mqd_mgr->allocate_mqd(mqd_mgr->dev, &q->properties); |
---|
| 366 | + dqm_lock(dqm); |
---|
| 367 | + |
---|
| 368 | + if (!q->mqd_mem_obj) { |
---|
| 369 | + retval = -ENOMEM; |
---|
| 370 | + goto out_deallocate_doorbell; |
---|
| 371 | + } |
---|
| 372 | + mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, |
---|
| 373 | + &q->gart_mqd_addr, &q->properties); |
---|
| 374 | + if (q->properties.is_active) { |
---|
| 375 | + if (!dqm->sched_running) { |
---|
| 376 | + WARN_ONCE(1, "Load non-HWS mqd while stopped\n"); |
---|
| 377 | + goto add_queue_to_list; |
---|
| 378 | + } |
---|
| 379 | + |
---|
| 380 | + if (WARN(q->process->mm != current->mm, |
---|
| 381 | + "should only run in user thread")) |
---|
| 382 | + retval = -EFAULT; |
---|
| 383 | + else |
---|
| 384 | + retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, |
---|
| 385 | + q->queue, &q->properties, current->mm); |
---|
| 386 | + if (retval) |
---|
| 387 | + goto out_free_mqd; |
---|
| 388 | + } |
---|
| 389 | + |
---|
| 390 | +add_queue_to_list: |
---|
296 | 391 | list_add(&q->list, &qpd->queues_list); |
---|
297 | 392 | qpd->queue_count++; |
---|
298 | 393 | if (q->properties.is_active) |
---|
299 | | - dqm->queue_count++; |
---|
300 | | - |
---|
301 | | - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) |
---|
302 | | - dqm->sdma_queue_count++; |
---|
| 394 | + increment_queue_count(dqm, qpd, q); |
---|
303 | 395 | |
---|
304 | 396 | /* |
---|
305 | 397 | * Unconditionally increment this counter, regardless of the queue's |
---|
.. | .. |
---|
308 | 400 | dqm->total_queue_count++; |
---|
309 | 401 | pr_debug("Total of %d queues are accountable so far\n", |
---|
310 | 402 | dqm->total_queue_count); |
---|
| 403 | + goto out_unlock; |
---|
311 | 404 | |
---|
| 405 | +out_free_mqd: |
---|
| 406 | + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
| 407 | +out_deallocate_doorbell: |
---|
| 408 | + deallocate_doorbell(qpd, q); |
---|
| 409 | +out_deallocate_hqd: |
---|
| 410 | + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) |
---|
| 411 | + deallocate_hqd(dqm, q); |
---|
| 412 | + else if (q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 413 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) |
---|
| 414 | + deallocate_sdma_queue(dqm, q); |
---|
| 415 | +deallocate_vmid: |
---|
| 416 | + if (list_empty(&qpd->queues_list)) |
---|
| 417 | + deallocate_vmid(dqm, qpd, q); |
---|
312 | 418 | out_unlock: |
---|
313 | 419 | dqm_unlock(dqm); |
---|
314 | 420 | return retval; |
---|
.. | .. |
---|
354 | 460 | dqm->allocated_queues[q->pipe] |= (1 << q->queue); |
---|
355 | 461 | } |
---|
356 | 462 | |
---|
357 | | -static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, |
---|
358 | | - struct queue *q, |
---|
359 | | - struct qcm_process_device *qpd) |
---|
360 | | -{ |
---|
361 | | - struct mqd_manager *mqd_mgr; |
---|
362 | | - int retval; |
---|
363 | | - |
---|
364 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); |
---|
365 | | - if (!mqd_mgr) |
---|
366 | | - return -ENOMEM; |
---|
367 | | - |
---|
368 | | - retval = allocate_hqd(dqm, q); |
---|
369 | | - if (retval) |
---|
370 | | - return retval; |
---|
371 | | - |
---|
372 | | - retval = allocate_doorbell(qpd, q); |
---|
373 | | - if (retval) |
---|
374 | | - goto out_deallocate_hqd; |
---|
375 | | - |
---|
376 | | - retval = mqd_mgr->init_mqd(mqd_mgr, &q->mqd, &q->mqd_mem_obj, |
---|
377 | | - &q->gart_mqd_addr, &q->properties); |
---|
378 | | - if (retval) |
---|
379 | | - goto out_deallocate_doorbell; |
---|
380 | | - |
---|
381 | | - pr_debug("Loading mqd to hqd on pipe %d, queue %d\n", |
---|
382 | | - q->pipe, q->queue); |
---|
383 | | - |
---|
384 | | - dqm->dev->kfd2kgd->set_scratch_backing_va( |
---|
385 | | - dqm->dev->kgd, qpd->sh_hidden_private_base, qpd->vmid); |
---|
386 | | - |
---|
387 | | - if (!q->properties.is_active) |
---|
388 | | - return 0; |
---|
389 | | - |
---|
390 | | - if (WARN(q->process->mm != current->mm, |
---|
391 | | - "should only run in user thread")) |
---|
392 | | - retval = -EFAULT; |
---|
393 | | - else |
---|
394 | | - retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, q->queue, |
---|
395 | | - &q->properties, current->mm); |
---|
396 | | - if (retval) |
---|
397 | | - goto out_uninit_mqd; |
---|
398 | | - |
---|
399 | | - return 0; |
---|
400 | | - |
---|
401 | | -out_uninit_mqd: |
---|
402 | | - mqd_mgr->uninit_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
403 | | -out_deallocate_doorbell: |
---|
404 | | - deallocate_doorbell(qpd, q); |
---|
405 | | -out_deallocate_hqd: |
---|
406 | | - deallocate_hqd(dqm, q); |
---|
407 | | - |
---|
408 | | - return retval; |
---|
409 | | -} |
---|
410 | | - |
---|
411 | 463 | /* Access to DQM has to be locked before calling destroy_queue_nocpsch_locked |
---|
412 | 464 | * to avoid asynchronized access |
---|
413 | 465 | */ |
---|
.. | .. |
---|
418 | 470 | int retval; |
---|
419 | 471 | struct mqd_manager *mqd_mgr; |
---|
420 | 472 | |
---|
421 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, |
---|
422 | | - get_mqd_type_from_queue_type(q->properties.type)); |
---|
423 | | - if (!mqd_mgr) |
---|
424 | | - return -ENOMEM; |
---|
| 473 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 474 | + q->properties.type)]; |
---|
425 | 475 | |
---|
426 | | - if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) { |
---|
| 476 | + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) |
---|
427 | 477 | deallocate_hqd(dqm, q); |
---|
428 | | - } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { |
---|
429 | | - dqm->sdma_queue_count--; |
---|
430 | | - deallocate_sdma_queue(dqm, q->sdma_id); |
---|
431 | | - } else { |
---|
| 478 | + else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) |
---|
| 479 | + deallocate_sdma_queue(dqm, q); |
---|
| 480 | + else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) |
---|
| 481 | + deallocate_sdma_queue(dqm, q); |
---|
| 482 | + else { |
---|
432 | 483 | pr_debug("q->properties.type %d is invalid\n", |
---|
433 | 484 | q->properties.type); |
---|
434 | 485 | return -EINVAL; |
---|
.. | .. |
---|
437 | 488 | |
---|
438 | 489 | deallocate_doorbell(qpd, q); |
---|
439 | 490 | |
---|
| 491 | + if (!dqm->sched_running) { |
---|
| 492 | + WARN_ONCE(1, "Destroy non-HWS queue while stopped\n"); |
---|
| 493 | + return 0; |
---|
| 494 | + } |
---|
| 495 | + |
---|
440 | 496 | retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd, |
---|
441 | 497 | KFD_PREEMPT_TYPE_WAVEFRONT_RESET, |
---|
442 | 498 | KFD_UNMAP_LATENCY_MS, |
---|
443 | 499 | q->pipe, q->queue); |
---|
444 | 500 | if (retval == -ETIME) |
---|
445 | 501 | qpd->reset_wavefronts = true; |
---|
446 | | - |
---|
447 | | - mqd_mgr->uninit_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
448 | 502 | |
---|
449 | 503 | list_del(&q->list); |
---|
450 | 504 | if (list_empty(&qpd->queues_list)) { |
---|
.. | .. |
---|
463 | 517 | } |
---|
464 | 518 | qpd->queue_count--; |
---|
465 | 519 | if (q->properties.is_active) |
---|
466 | | - dqm->queue_count--; |
---|
| 520 | + decrement_queue_count(dqm, qpd, q); |
---|
467 | 521 | |
---|
468 | 522 | return retval; |
---|
469 | 523 | } |
---|
.. | .. |
---|
473 | 527 | struct queue *q) |
---|
474 | 528 | { |
---|
475 | 529 | int retval; |
---|
| 530 | + uint64_t sdma_val = 0; |
---|
| 531 | + struct kfd_process_device *pdd = qpd_to_pdd(qpd); |
---|
| 532 | + struct mqd_manager *mqd_mgr = |
---|
| 533 | + dqm->mqd_mgrs[get_mqd_type_from_queue_type(q->properties.type)]; |
---|
| 534 | + |
---|
| 535 | + /* Get the SDMA queue stats */ |
---|
| 536 | + if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || |
---|
| 537 | + (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { |
---|
| 538 | + retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr, |
---|
| 539 | + &sdma_val); |
---|
| 540 | + if (retval) |
---|
| 541 | + pr_err("Failed to read SDMA queue counter for queue: %d\n", |
---|
| 542 | + q->properties.queue_id); |
---|
| 543 | + } |
---|
476 | 544 | |
---|
477 | 545 | dqm_lock(dqm); |
---|
478 | 546 | retval = destroy_queue_nocpsch_locked(dqm, qpd, q); |
---|
| 547 | + if (!retval) |
---|
| 548 | + pdd->sdma_past_activity_counter += sdma_val; |
---|
479 | 549 | dqm_unlock(dqm); |
---|
| 550 | + |
---|
| 551 | + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
480 | 552 | |
---|
481 | 553 | return retval; |
---|
482 | 554 | } |
---|
483 | 555 | |
---|
484 | 556 | static int update_queue(struct device_queue_manager *dqm, struct queue *q) |
---|
485 | 557 | { |
---|
486 | | - int retval; |
---|
| 558 | + int retval = 0; |
---|
487 | 559 | struct mqd_manager *mqd_mgr; |
---|
488 | 560 | struct kfd_process_device *pdd; |
---|
489 | 561 | bool prev_active = false; |
---|
.. | .. |
---|
494 | 566 | retval = -ENODEV; |
---|
495 | 567 | goto out_unlock; |
---|
496 | 568 | } |
---|
497 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, |
---|
498 | | - get_mqd_type_from_queue_type(q->properties.type)); |
---|
499 | | - if (!mqd_mgr) { |
---|
500 | | - retval = -ENOMEM; |
---|
501 | | - goto out_unlock; |
---|
502 | | - } |
---|
503 | | - /* |
---|
504 | | - * Eviction state logic: we only mark active queues as evicted |
---|
505 | | - * to avoid the overhead of restoring inactive queues later |
---|
506 | | - */ |
---|
507 | | - if (pdd->qpd.evicted) |
---|
508 | | - q->properties.is_evicted = (q->properties.queue_size > 0 && |
---|
509 | | - q->properties.queue_percent > 0 && |
---|
510 | | - q->properties.queue_address != 0); |
---|
| 569 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 570 | + q->properties.type)]; |
---|
511 | 571 | |
---|
512 | 572 | /* Save previous activity state for counters */ |
---|
513 | 573 | prev_active = q->properties.is_active; |
---|
.. | .. |
---|
522 | 582 | } |
---|
523 | 583 | } else if (prev_active && |
---|
524 | 584 | (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || |
---|
525 | | - q->properties.type == KFD_QUEUE_TYPE_SDMA)) { |
---|
| 585 | + q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 586 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { |
---|
| 587 | + |
---|
| 588 | + if (!dqm->sched_running) { |
---|
| 589 | + WARN_ONCE(1, "Update non-HWS queue while stopped\n"); |
---|
| 590 | + goto out_unlock; |
---|
| 591 | + } |
---|
| 592 | + |
---|
526 | 593 | retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd, |
---|
527 | 594 | KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN, |
---|
528 | 595 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); |
---|
.. | .. |
---|
532 | 599 | } |
---|
533 | 600 | } |
---|
534 | 601 | |
---|
535 | | - retval = mqd_mgr->update_mqd(mqd_mgr, q->mqd, &q->properties); |
---|
| 602 | + mqd_mgr->update_mqd(mqd_mgr, q->mqd, &q->properties); |
---|
536 | 603 | |
---|
537 | 604 | /* |
---|
538 | 605 | * check active state vs. the previous state and modify |
---|
539 | 606 | * counter accordingly. map_queues_cpsch uses the |
---|
540 | | - * dqm->queue_count to determine whether a new runlist must be |
---|
| 607 | + * dqm->active_queue_count to determine whether a new runlist must be |
---|
541 | 608 | * uploaded. |
---|
542 | 609 | */ |
---|
543 | | - if (q->properties.is_active && !prev_active) |
---|
544 | | - dqm->queue_count++; |
---|
545 | | - else if (!q->properties.is_active && prev_active) |
---|
546 | | - dqm->queue_count--; |
---|
| 610 | + if (q->properties.is_active && !prev_active) { |
---|
| 611 | + increment_queue_count(dqm, &pdd->qpd, q); |
---|
| 612 | + } else if (!q->properties.is_active && prev_active) { |
---|
| 613 | + decrement_queue_count(dqm, &pdd->qpd, q); |
---|
| 614 | + } else if (q->gws && !q->properties.is_gws) { |
---|
| 615 | + if (q->properties.is_active) { |
---|
| 616 | + dqm->gws_queue_count++; |
---|
| 617 | + pdd->qpd.mapped_gws_queue = true; |
---|
| 618 | + } |
---|
| 619 | + q->properties.is_gws = true; |
---|
| 620 | + } else if (!q->gws && q->properties.is_gws) { |
---|
| 621 | + if (q->properties.is_active) { |
---|
| 622 | + dqm->gws_queue_count--; |
---|
| 623 | + pdd->qpd.mapped_gws_queue = false; |
---|
| 624 | + } |
---|
| 625 | + q->properties.is_gws = false; |
---|
| 626 | + } |
---|
547 | 627 | |
---|
548 | 628 | if (dqm->sched_policy != KFD_SCHED_POLICY_NO_HWS) |
---|
549 | 629 | retval = map_queues_cpsch(dqm); |
---|
550 | 630 | else if (q->properties.is_active && |
---|
551 | 631 | (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || |
---|
552 | | - q->properties.type == KFD_QUEUE_TYPE_SDMA)) { |
---|
| 632 | + q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 633 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { |
---|
553 | 634 | if (WARN(q->process->mm != current->mm, |
---|
554 | 635 | "should only run in user thread")) |
---|
555 | 636 | retval = -EFAULT; |
---|
.. | .. |
---|
564 | 645 | return retval; |
---|
565 | 646 | } |
---|
566 | 647 | |
---|
567 | | -static struct mqd_manager *get_mqd_manager( |
---|
568 | | - struct device_queue_manager *dqm, enum KFD_MQD_TYPE type) |
---|
569 | | -{ |
---|
570 | | - struct mqd_manager *mqd_mgr; |
---|
571 | | - |
---|
572 | | - if (WARN_ON(type >= KFD_MQD_TYPE_MAX)) |
---|
573 | | - return NULL; |
---|
574 | | - |
---|
575 | | - pr_debug("mqd type %d\n", type); |
---|
576 | | - |
---|
577 | | - mqd_mgr = dqm->mqd_mgrs[type]; |
---|
578 | | - if (!mqd_mgr) { |
---|
579 | | - mqd_mgr = mqd_manager_init(type, dqm->dev); |
---|
580 | | - if (!mqd_mgr) |
---|
581 | | - pr_err("mqd manager is NULL"); |
---|
582 | | - dqm->mqd_mgrs[type] = mqd_mgr; |
---|
583 | | - } |
---|
584 | | - |
---|
585 | | - return mqd_mgr; |
---|
586 | | -} |
---|
587 | | - |
---|
588 | 648 | static int evict_process_queues_nocpsch(struct device_queue_manager *dqm, |
---|
589 | 649 | struct qcm_process_device *qpd) |
---|
590 | 650 | { |
---|
591 | 651 | struct queue *q; |
---|
592 | 652 | struct mqd_manager *mqd_mgr; |
---|
593 | 653 | struct kfd_process_device *pdd; |
---|
594 | | - int retval = 0; |
---|
| 654 | + int retval, ret = 0; |
---|
595 | 655 | |
---|
596 | 656 | dqm_lock(dqm); |
---|
597 | 657 | if (qpd->evicted++ > 0) /* already evicted, do nothing */ |
---|
598 | 658 | goto out; |
---|
599 | 659 | |
---|
600 | 660 | pdd = qpd_to_pdd(qpd); |
---|
601 | | - pr_info_ratelimited("Evicting PASID %u queues\n", |
---|
| 661 | + pr_debug_ratelimited("Evicting PASID 0x%x queues\n", |
---|
602 | 662 | pdd->process->pasid); |
---|
603 | 663 | |
---|
604 | | - /* unactivate all active queues on the qpd */ |
---|
| 664 | + pdd->last_evict_timestamp = get_jiffies_64(); |
---|
| 665 | + /* Mark all queues as evicted. Deactivate all active queues on |
---|
| 666 | + * the qpd. |
---|
| 667 | + */ |
---|
605 | 668 | list_for_each_entry(q, &qpd->queues_list, list) { |
---|
| 669 | + q->properties.is_evicted = true; |
---|
606 | 670 | if (!q->properties.is_active) |
---|
607 | 671 | continue; |
---|
608 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, |
---|
609 | | - get_mqd_type_from_queue_type(q->properties.type)); |
---|
610 | | - if (!mqd_mgr) { /* should not be here */ |
---|
611 | | - pr_err("Cannot evict queue, mqd mgr is NULL\n"); |
---|
612 | | - retval = -ENOMEM; |
---|
613 | | - goto out; |
---|
614 | | - } |
---|
615 | | - q->properties.is_evicted = true; |
---|
| 672 | + |
---|
| 673 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 674 | + q->properties.type)]; |
---|
616 | 675 | q->properties.is_active = false; |
---|
| 676 | + decrement_queue_count(dqm, qpd, q); |
---|
| 677 | + |
---|
| 678 | + if (WARN_ONCE(!dqm->sched_running, "Evict when stopped\n")) |
---|
| 679 | + continue; |
---|
| 680 | + |
---|
617 | 681 | retval = mqd_mgr->destroy_mqd(mqd_mgr, q->mqd, |
---|
618 | 682 | KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN, |
---|
619 | 683 | KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); |
---|
620 | | - if (retval) |
---|
621 | | - goto out; |
---|
622 | | - dqm->queue_count--; |
---|
| 684 | + if (retval && !ret) |
---|
| 685 | + /* Return the first error, but keep going to |
---|
| 686 | + * maintain a consistent eviction state |
---|
| 687 | + */ |
---|
| 688 | + ret = retval; |
---|
623 | 689 | } |
---|
624 | 690 | |
---|
625 | 691 | out: |
---|
626 | 692 | dqm_unlock(dqm); |
---|
627 | | - return retval; |
---|
| 693 | + return ret; |
---|
628 | 694 | } |
---|
629 | 695 | |
---|
630 | 696 | static int evict_process_queues_cpsch(struct device_queue_manager *dqm, |
---|
.. | .. |
---|
639 | 705 | goto out; |
---|
640 | 706 | |
---|
641 | 707 | pdd = qpd_to_pdd(qpd); |
---|
642 | | - pr_info_ratelimited("Evicting PASID %u queues\n", |
---|
| 708 | + pr_debug_ratelimited("Evicting PASID 0x%x queues\n", |
---|
643 | 709 | pdd->process->pasid); |
---|
644 | 710 | |
---|
645 | | - /* unactivate all active queues on the qpd */ |
---|
| 711 | + /* Mark all queues as evicted. Deactivate all active queues on |
---|
| 712 | + * the qpd. |
---|
| 713 | + */ |
---|
646 | 714 | list_for_each_entry(q, &qpd->queues_list, list) { |
---|
| 715 | + q->properties.is_evicted = true; |
---|
647 | 716 | if (!q->properties.is_active) |
---|
648 | 717 | continue; |
---|
649 | | - q->properties.is_evicted = true; |
---|
| 718 | + |
---|
650 | 719 | q->properties.is_active = false; |
---|
651 | | - dqm->queue_count--; |
---|
| 720 | + decrement_queue_count(dqm, qpd, q); |
---|
652 | 721 | } |
---|
| 722 | + pdd->last_evict_timestamp = get_jiffies_64(); |
---|
653 | 723 | retval = execute_queues_cpsch(dqm, |
---|
654 | 724 | qpd->is_debug ? |
---|
655 | 725 | KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES : |
---|
.. | .. |
---|
667 | 737 | struct queue *q; |
---|
668 | 738 | struct mqd_manager *mqd_mgr; |
---|
669 | 739 | struct kfd_process_device *pdd; |
---|
670 | | - uint32_t pd_base; |
---|
671 | | - int retval = 0; |
---|
| 740 | + uint64_t pd_base; |
---|
| 741 | + uint64_t eviction_duration; |
---|
| 742 | + int retval, ret = 0; |
---|
672 | 743 | |
---|
673 | 744 | pdd = qpd_to_pdd(qpd); |
---|
674 | 745 | /* Retrieve PD base */ |
---|
675 | | - pd_base = dqm->dev->kfd2kgd->get_process_page_dir(pdd->vm); |
---|
| 746 | + pd_base = amdgpu_amdkfd_gpuvm_get_process_page_dir(pdd->vm); |
---|
676 | 747 | |
---|
677 | 748 | dqm_lock(dqm); |
---|
678 | 749 | if (WARN_ON_ONCE(!qpd->evicted)) /* already restored, do nothing */ |
---|
.. | .. |
---|
682 | 753 | goto out; |
---|
683 | 754 | } |
---|
684 | 755 | |
---|
685 | | - pr_info_ratelimited("Restoring PASID %u queues\n", |
---|
| 756 | + pr_debug_ratelimited("Restoring PASID 0x%x queues\n", |
---|
686 | 757 | pdd->process->pasid); |
---|
687 | 758 | |
---|
688 | 759 | /* Update PD Base in QPD */ |
---|
689 | 760 | qpd->page_table_base = pd_base; |
---|
690 | | - pr_debug("Updated PD address to 0x%08x\n", pd_base); |
---|
| 761 | + pr_debug("Updated PD address to 0x%llx\n", pd_base); |
---|
691 | 762 | |
---|
692 | 763 | if (!list_empty(&qpd->queues_list)) { |
---|
693 | 764 | dqm->dev->kfd2kgd->set_vm_context_page_table_base( |
---|
.. | .. |
---|
702 | 773 | */ |
---|
703 | 774 | mm = get_task_mm(pdd->process->lead_thread); |
---|
704 | 775 | if (!mm) { |
---|
705 | | - retval = -EFAULT; |
---|
| 776 | + ret = -EFAULT; |
---|
706 | 777 | goto out; |
---|
707 | 778 | } |
---|
708 | 779 | |
---|
709 | | - /* activate all active queues on the qpd */ |
---|
| 780 | + /* Remove the eviction flags. Activate queues that are not |
---|
| 781 | + * inactive for other reasons. |
---|
| 782 | + */ |
---|
710 | 783 | list_for_each_entry(q, &qpd->queues_list, list) { |
---|
711 | | - if (!q->properties.is_evicted) |
---|
712 | | - continue; |
---|
713 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, |
---|
714 | | - get_mqd_type_from_queue_type(q->properties.type)); |
---|
715 | | - if (!mqd_mgr) { /* should not be here */ |
---|
716 | | - pr_err("Cannot restore queue, mqd mgr is NULL\n"); |
---|
717 | | - retval = -ENOMEM; |
---|
718 | | - goto out; |
---|
719 | | - } |
---|
720 | 784 | q->properties.is_evicted = false; |
---|
| 785 | + if (!QUEUE_IS_ACTIVE(q->properties)) |
---|
| 786 | + continue; |
---|
| 787 | + |
---|
| 788 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 789 | + q->properties.type)]; |
---|
721 | 790 | q->properties.is_active = true; |
---|
| 791 | + increment_queue_count(dqm, qpd, q); |
---|
| 792 | + |
---|
| 793 | + if (WARN_ONCE(!dqm->sched_running, "Restore when stopped\n")) |
---|
| 794 | + continue; |
---|
| 795 | + |
---|
722 | 796 | retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, |
---|
723 | 797 | q->queue, &q->properties, mm); |
---|
724 | | - if (retval) |
---|
725 | | - goto out; |
---|
726 | | - dqm->queue_count++; |
---|
| 798 | + if (retval && !ret) |
---|
| 799 | + /* Return the first error, but keep going to |
---|
| 800 | + * maintain a consistent eviction state |
---|
| 801 | + */ |
---|
| 802 | + ret = retval; |
---|
727 | 803 | } |
---|
728 | 804 | qpd->evicted = 0; |
---|
| 805 | + eviction_duration = get_jiffies_64() - pdd->last_evict_timestamp; |
---|
| 806 | + atomic64_add(eviction_duration, &pdd->evict_duration_counter); |
---|
729 | 807 | out: |
---|
730 | 808 | if (mm) |
---|
731 | 809 | mmput(mm); |
---|
732 | 810 | dqm_unlock(dqm); |
---|
733 | | - return retval; |
---|
| 811 | + return ret; |
---|
734 | 812 | } |
---|
735 | 813 | |
---|
736 | 814 | static int restore_process_queues_cpsch(struct device_queue_manager *dqm, |
---|
.. | .. |
---|
738 | 816 | { |
---|
739 | 817 | struct queue *q; |
---|
740 | 818 | struct kfd_process_device *pdd; |
---|
741 | | - uint32_t pd_base; |
---|
| 819 | + uint64_t pd_base; |
---|
| 820 | + uint64_t eviction_duration; |
---|
742 | 821 | int retval = 0; |
---|
743 | 822 | |
---|
744 | 823 | pdd = qpd_to_pdd(qpd); |
---|
745 | 824 | /* Retrieve PD base */ |
---|
746 | | - pd_base = dqm->dev->kfd2kgd->get_process_page_dir(pdd->vm); |
---|
| 825 | + pd_base = amdgpu_amdkfd_gpuvm_get_process_page_dir(pdd->vm); |
---|
747 | 826 | |
---|
748 | 827 | dqm_lock(dqm); |
---|
749 | 828 | if (WARN_ON_ONCE(!qpd->evicted)) /* already restored, do nothing */ |
---|
.. | .. |
---|
753 | 832 | goto out; |
---|
754 | 833 | } |
---|
755 | 834 | |
---|
756 | | - pr_info_ratelimited("Restoring PASID %u queues\n", |
---|
| 835 | + pr_debug_ratelimited("Restoring PASID 0x%x queues\n", |
---|
757 | 836 | pdd->process->pasid); |
---|
758 | 837 | |
---|
759 | 838 | /* Update PD Base in QPD */ |
---|
760 | 839 | qpd->page_table_base = pd_base; |
---|
761 | | - pr_debug("Updated PD address to 0x%08x\n", pd_base); |
---|
| 840 | + pr_debug("Updated PD address to 0x%llx\n", pd_base); |
---|
762 | 841 | |
---|
763 | 842 | /* activate all active queues on the qpd */ |
---|
764 | 843 | list_for_each_entry(q, &qpd->queues_list, list) { |
---|
765 | | - if (!q->properties.is_evicted) |
---|
766 | | - continue; |
---|
767 | 844 | q->properties.is_evicted = false; |
---|
| 845 | + if (!QUEUE_IS_ACTIVE(q->properties)) |
---|
| 846 | + continue; |
---|
| 847 | + |
---|
768 | 848 | q->properties.is_active = true; |
---|
769 | | - dqm->queue_count++; |
---|
| 849 | + increment_queue_count(dqm, &pdd->qpd, q); |
---|
770 | 850 | } |
---|
771 | 851 | retval = execute_queues_cpsch(dqm, |
---|
772 | 852 | KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
---|
773 | | - if (!retval) |
---|
774 | | - qpd->evicted = 0; |
---|
| 853 | + qpd->evicted = 0; |
---|
| 854 | + eviction_duration = get_jiffies_64() - pdd->last_evict_timestamp; |
---|
| 855 | + atomic64_add(eviction_duration, &pdd->evict_duration_counter); |
---|
775 | 856 | out: |
---|
776 | 857 | dqm_unlock(dqm); |
---|
777 | 858 | return retval; |
---|
.. | .. |
---|
782 | 863 | { |
---|
783 | 864 | struct device_process_node *n; |
---|
784 | 865 | struct kfd_process_device *pdd; |
---|
785 | | - uint32_t pd_base; |
---|
| 866 | + uint64_t pd_base; |
---|
786 | 867 | int retval; |
---|
787 | 868 | |
---|
788 | 869 | n = kzalloc(sizeof(*n), GFP_KERNEL); |
---|
.. | .. |
---|
793 | 874 | |
---|
794 | 875 | pdd = qpd_to_pdd(qpd); |
---|
795 | 876 | /* Retrieve PD base */ |
---|
796 | | - pd_base = dqm->dev->kfd2kgd->get_process_page_dir(pdd->vm); |
---|
| 877 | + pd_base = amdgpu_amdkfd_gpuvm_get_process_page_dir(pdd->vm); |
---|
797 | 878 | |
---|
798 | 879 | dqm_lock(dqm); |
---|
799 | 880 | list_add(&n->list, &dqm->queues); |
---|
800 | 881 | |
---|
801 | 882 | /* Update PD Base in QPD */ |
---|
802 | 883 | qpd->page_table_base = pd_base; |
---|
| 884 | + pr_debug("Updated PD address to 0x%llx\n", pd_base); |
---|
803 | 885 | |
---|
804 | 886 | retval = dqm->asic_ops.update_qpd(dqm, qpd); |
---|
805 | 887 | |
---|
806 | | - if (dqm->processes_count++ == 0) |
---|
807 | | - dqm->dev->kfd2kgd->set_compute_idle(dqm->dev->kgd, false); |
---|
| 888 | + dqm->processes_count++; |
---|
808 | 889 | |
---|
809 | 890 | dqm_unlock(dqm); |
---|
| 891 | + |
---|
| 892 | + /* Outside the DQM lock because under the DQM lock we can't do |
---|
| 893 | + * reclaim or take other locks that others hold while reclaiming. |
---|
| 894 | + */ |
---|
| 895 | + kfd_inc_compute_active(dqm->dev); |
---|
810 | 896 | |
---|
811 | 897 | return retval; |
---|
812 | 898 | } |
---|
.. | .. |
---|
827 | 913 | if (qpd == cur->qpd) { |
---|
828 | 914 | list_del(&cur->list); |
---|
829 | 915 | kfree(cur); |
---|
830 | | - if (--dqm->processes_count == 0) |
---|
831 | | - dqm->dev->kfd2kgd->set_compute_idle( |
---|
832 | | - dqm->dev->kgd, true); |
---|
| 916 | + dqm->processes_count--; |
---|
833 | 917 | goto out; |
---|
834 | 918 | } |
---|
835 | 919 | } |
---|
.. | .. |
---|
837 | 921 | retval = 1; |
---|
838 | 922 | out: |
---|
839 | 923 | dqm_unlock(dqm); |
---|
| 924 | + |
---|
| 925 | + /* Outside the DQM lock because under the DQM lock we can't do |
---|
| 926 | + * reclaim or take other locks that others hold while reclaiming. |
---|
| 927 | + */ |
---|
| 928 | + if (!retval) |
---|
| 929 | + kfd_dec_compute_active(dqm->dev); |
---|
| 930 | + |
---|
840 | 931 | return retval; |
---|
841 | 932 | } |
---|
842 | 933 | |
---|
843 | 934 | static int |
---|
844 | | -set_pasid_vmid_mapping(struct device_queue_manager *dqm, unsigned int pasid, |
---|
| 935 | +set_pasid_vmid_mapping(struct device_queue_manager *dqm, u32 pasid, |
---|
845 | 936 | unsigned int vmid) |
---|
846 | 937 | { |
---|
847 | | - uint32_t pasid_mapping; |
---|
848 | | - |
---|
849 | | - pasid_mapping = (pasid == 0) ? 0 : |
---|
850 | | - (uint32_t)pasid | |
---|
851 | | - ATC_VMID_PASID_MAPPING_VALID; |
---|
852 | | - |
---|
853 | 938 | return dqm->dev->kfd2kgd->set_pasid_vmid_mapping( |
---|
854 | | - dqm->dev->kgd, pasid_mapping, |
---|
855 | | - vmid); |
---|
| 939 | + dqm->dev->kgd, pasid, vmid); |
---|
856 | 940 | } |
---|
857 | 941 | |
---|
858 | 942 | static void init_interrupts(struct device_queue_manager *dqm) |
---|
.. | .. |
---|
877 | 961 | |
---|
878 | 962 | mutex_init(&dqm->lock_hidden); |
---|
879 | 963 | INIT_LIST_HEAD(&dqm->queues); |
---|
880 | | - dqm->queue_count = dqm->next_pipe_to_allocate = 0; |
---|
881 | | - dqm->sdma_queue_count = 0; |
---|
| 964 | + dqm->active_queue_count = dqm->next_pipe_to_allocate = 0; |
---|
| 965 | + dqm->active_cp_queue_count = 0; |
---|
| 966 | + dqm->gws_queue_count = 0; |
---|
882 | 967 | |
---|
883 | 968 | for (pipe = 0; pipe < get_pipes_per_mec(dqm); pipe++) { |
---|
884 | 969 | int pipe_offset = pipe * get_queues_per_pipe(dqm); |
---|
885 | 970 | |
---|
886 | 971 | for (queue = 0; queue < get_queues_per_pipe(dqm); queue++) |
---|
887 | 972 | if (test_bit(pipe_offset + queue, |
---|
888 | | - dqm->dev->shared_resources.queue_bitmap)) |
---|
| 973 | + dqm->dev->shared_resources.cp_queue_bitmap)) |
---|
889 | 974 | dqm->allocated_queues[pipe] |= 1 << queue; |
---|
890 | 975 | } |
---|
891 | 976 | |
---|
892 | | - dqm->vmid_bitmap = (1 << dqm->dev->vm_info.vmid_num_kfd) - 1; |
---|
893 | | - dqm->sdma_bitmap = (1 << get_num_sdma_queues(dqm)) - 1; |
---|
| 977 | + memset(dqm->vmid_pasid, 0, sizeof(dqm->vmid_pasid)); |
---|
| 978 | + |
---|
| 979 | + dqm->sdma_bitmap = ~0ULL >> (64 - get_num_sdma_queues(dqm)); |
---|
| 980 | + dqm->xgmi_sdma_bitmap = ~0ULL >> (64 - get_num_xgmi_sdma_queues(dqm)); |
---|
894 | 981 | |
---|
895 | 982 | return 0; |
---|
896 | 983 | } |
---|
.. | .. |
---|
899 | 986 | { |
---|
900 | 987 | int i; |
---|
901 | 988 | |
---|
902 | | - WARN_ON(dqm->queue_count > 0 || dqm->processes_count > 0); |
---|
| 989 | + WARN_ON(dqm->active_queue_count > 0 || dqm->processes_count > 0); |
---|
903 | 990 | |
---|
904 | 991 | kfree(dqm->allocated_queues); |
---|
905 | 992 | for (i = 0 ; i < KFD_MQD_TYPE_MAX ; i++) |
---|
906 | 993 | kfree(dqm->mqd_mgrs[i]); |
---|
907 | 994 | mutex_destroy(&dqm->lock_hidden); |
---|
908 | | - kfd_gtt_sa_free(dqm->dev, dqm->pipeline_mem); |
---|
909 | 995 | } |
---|
910 | 996 | |
---|
911 | 997 | static int start_nocpsch(struct device_queue_manager *dqm) |
---|
912 | 998 | { |
---|
| 999 | + pr_info("SW scheduler is used"); |
---|
913 | 1000 | init_interrupts(dqm); |
---|
914 | | - return pm_init(&dqm->packets, dqm); |
---|
| 1001 | + |
---|
| 1002 | + if (dqm->dev->device_info->asic_family == CHIP_HAWAII) |
---|
| 1003 | + return pm_init(&dqm->packets, dqm); |
---|
| 1004 | + dqm->sched_running = true; |
---|
| 1005 | + |
---|
| 1006 | + return 0; |
---|
915 | 1007 | } |
---|
916 | 1008 | |
---|
917 | 1009 | static int stop_nocpsch(struct device_queue_manager *dqm) |
---|
918 | 1010 | { |
---|
919 | | - pm_uninit(&dqm->packets); |
---|
| 1011 | + if (dqm->dev->device_info->asic_family == CHIP_HAWAII) |
---|
| 1012 | + pm_uninit(&dqm->packets, false); |
---|
| 1013 | + dqm->sched_running = false; |
---|
| 1014 | + |
---|
920 | 1015 | return 0; |
---|
921 | 1016 | } |
---|
922 | 1017 | |
---|
| 1018 | +static void pre_reset(struct device_queue_manager *dqm) |
---|
| 1019 | +{ |
---|
| 1020 | + dqm_lock(dqm); |
---|
| 1021 | + dqm->is_resetting = true; |
---|
| 1022 | + dqm_unlock(dqm); |
---|
| 1023 | +} |
---|
| 1024 | + |
---|
923 | 1025 | static int allocate_sdma_queue(struct device_queue_manager *dqm, |
---|
924 | | - unsigned int *sdma_queue_id) |
---|
| 1026 | + struct queue *q) |
---|
925 | 1027 | { |
---|
926 | 1028 | int bit; |
---|
927 | 1029 | |
---|
928 | | - if (dqm->sdma_bitmap == 0) |
---|
929 | | - return -ENOMEM; |
---|
| 1030 | + if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { |
---|
| 1031 | + if (dqm->sdma_bitmap == 0) { |
---|
| 1032 | + pr_err("No more SDMA queue to allocate\n"); |
---|
| 1033 | + return -ENOMEM; |
---|
| 1034 | + } |
---|
930 | 1035 | |
---|
931 | | - bit = ffs(dqm->sdma_bitmap) - 1; |
---|
932 | | - dqm->sdma_bitmap &= ~(1 << bit); |
---|
933 | | - *sdma_queue_id = bit; |
---|
| 1036 | + bit = __ffs64(dqm->sdma_bitmap); |
---|
| 1037 | + dqm->sdma_bitmap &= ~(1ULL << bit); |
---|
| 1038 | + q->sdma_id = bit; |
---|
| 1039 | + q->properties.sdma_engine_id = q->sdma_id % |
---|
| 1040 | + get_num_sdma_engines(dqm); |
---|
| 1041 | + q->properties.sdma_queue_id = q->sdma_id / |
---|
| 1042 | + get_num_sdma_engines(dqm); |
---|
| 1043 | + } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { |
---|
| 1044 | + if (dqm->xgmi_sdma_bitmap == 0) { |
---|
| 1045 | + pr_err("No more XGMI SDMA queue to allocate\n"); |
---|
| 1046 | + return -ENOMEM; |
---|
| 1047 | + } |
---|
| 1048 | + bit = __ffs64(dqm->xgmi_sdma_bitmap); |
---|
| 1049 | + dqm->xgmi_sdma_bitmap &= ~(1ULL << bit); |
---|
| 1050 | + q->sdma_id = bit; |
---|
| 1051 | + /* sdma_engine_id is sdma id including |
---|
| 1052 | + * both PCIe-optimized SDMAs and XGMI- |
---|
| 1053 | + * optimized SDMAs. The calculation below |
---|
| 1054 | + * assumes the first N engines are always |
---|
| 1055 | + * PCIe-optimized ones |
---|
| 1056 | + */ |
---|
| 1057 | + q->properties.sdma_engine_id = get_num_sdma_engines(dqm) + |
---|
| 1058 | + q->sdma_id % get_num_xgmi_sdma_engines(dqm); |
---|
| 1059 | + q->properties.sdma_queue_id = q->sdma_id / |
---|
| 1060 | + get_num_xgmi_sdma_engines(dqm); |
---|
| 1061 | + } |
---|
| 1062 | + |
---|
| 1063 | + pr_debug("SDMA engine id: %d\n", q->properties.sdma_engine_id); |
---|
| 1064 | + pr_debug("SDMA queue id: %d\n", q->properties.sdma_queue_id); |
---|
934 | 1065 | |
---|
935 | 1066 | return 0; |
---|
936 | 1067 | } |
---|
937 | 1068 | |
---|
938 | 1069 | static void deallocate_sdma_queue(struct device_queue_manager *dqm, |
---|
939 | | - unsigned int sdma_queue_id) |
---|
| 1070 | + struct queue *q) |
---|
940 | 1071 | { |
---|
941 | | - if (sdma_queue_id >= get_num_sdma_queues(dqm)) |
---|
942 | | - return; |
---|
943 | | - dqm->sdma_bitmap |= (1 << sdma_queue_id); |
---|
944 | | -} |
---|
945 | | - |
---|
946 | | -static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm, |
---|
947 | | - struct queue *q, |
---|
948 | | - struct qcm_process_device *qpd) |
---|
949 | | -{ |
---|
950 | | - struct mqd_manager *mqd_mgr; |
---|
951 | | - int retval; |
---|
952 | | - |
---|
953 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); |
---|
954 | | - if (!mqd_mgr) |
---|
955 | | - return -ENOMEM; |
---|
956 | | - |
---|
957 | | - retval = allocate_sdma_queue(dqm, &q->sdma_id); |
---|
958 | | - if (retval) |
---|
959 | | - return retval; |
---|
960 | | - |
---|
961 | | - q->properties.sdma_queue_id = q->sdma_id / get_num_sdma_engines(dqm); |
---|
962 | | - q->properties.sdma_engine_id = q->sdma_id % get_num_sdma_engines(dqm); |
---|
963 | | - |
---|
964 | | - retval = allocate_doorbell(qpd, q); |
---|
965 | | - if (retval) |
---|
966 | | - goto out_deallocate_sdma_queue; |
---|
967 | | - |
---|
968 | | - pr_debug("SDMA id is: %d\n", q->sdma_id); |
---|
969 | | - pr_debug("SDMA queue id: %d\n", q->properties.sdma_queue_id); |
---|
970 | | - pr_debug("SDMA engine id: %d\n", q->properties.sdma_engine_id); |
---|
971 | | - |
---|
972 | | - dqm->asic_ops.init_sdma_vm(dqm, q, qpd); |
---|
973 | | - retval = mqd_mgr->init_mqd(mqd_mgr, &q->mqd, &q->mqd_mem_obj, |
---|
974 | | - &q->gart_mqd_addr, &q->properties); |
---|
975 | | - if (retval) |
---|
976 | | - goto out_deallocate_doorbell; |
---|
977 | | - |
---|
978 | | - retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, 0, 0, &q->properties, |
---|
979 | | - NULL); |
---|
980 | | - if (retval) |
---|
981 | | - goto out_uninit_mqd; |
---|
982 | | - |
---|
983 | | - return 0; |
---|
984 | | - |
---|
985 | | -out_uninit_mqd: |
---|
986 | | - mqd_mgr->uninit_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
987 | | -out_deallocate_doorbell: |
---|
988 | | - deallocate_doorbell(qpd, q); |
---|
989 | | -out_deallocate_sdma_queue: |
---|
990 | | - deallocate_sdma_queue(dqm, q->sdma_id); |
---|
991 | | - |
---|
992 | | - return retval; |
---|
| 1072 | + if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { |
---|
| 1073 | + if (q->sdma_id >= get_num_sdma_queues(dqm)) |
---|
| 1074 | + return; |
---|
| 1075 | + dqm->sdma_bitmap |= (1ULL << q->sdma_id); |
---|
| 1076 | + } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { |
---|
| 1077 | + if (q->sdma_id >= get_num_xgmi_sdma_queues(dqm)) |
---|
| 1078 | + return; |
---|
| 1079 | + dqm->xgmi_sdma_bitmap |= (1ULL << q->sdma_id); |
---|
| 1080 | + } |
---|
993 | 1081 | } |
---|
994 | 1082 | |
---|
995 | 1083 | /* |
---|
.. | .. |
---|
1008 | 1096 | mec = (i / dqm->dev->shared_resources.num_queue_per_pipe) |
---|
1009 | 1097 | / dqm->dev->shared_resources.num_pipe_per_mec; |
---|
1010 | 1098 | |
---|
1011 | | - if (!test_bit(i, dqm->dev->shared_resources.queue_bitmap)) |
---|
| 1099 | + if (!test_bit(i, dqm->dev->shared_resources.cp_queue_bitmap)) |
---|
1012 | 1100 | continue; |
---|
1013 | 1101 | |
---|
1014 | 1102 | /* only acquire queues from the first MEC */ |
---|
.. | .. |
---|
1024 | 1112 | break; |
---|
1025 | 1113 | } |
---|
1026 | 1114 | |
---|
1027 | | - res.queue_mask |= (1ull << i); |
---|
| 1115 | + res.queue_mask |= 1ull |
---|
| 1116 | + << amdgpu_queue_mask_bit_to_set_resource_bit( |
---|
| 1117 | + (struct amdgpu_device *)dqm->dev->kgd, i); |
---|
1028 | 1118 | } |
---|
1029 | | - res.gws_mask = res.oac_mask = res.gds_heap_base = |
---|
1030 | | - res.gds_heap_size = 0; |
---|
| 1119 | + res.gws_mask = ~0ull; |
---|
| 1120 | + res.oac_mask = res.gds_heap_base = res.gds_heap_size = 0; |
---|
1031 | 1121 | |
---|
1032 | 1122 | pr_debug("Scheduling resources:\n" |
---|
1033 | 1123 | "vmid mask: 0x%8X\n" |
---|
.. | .. |
---|
1039 | 1129 | |
---|
1040 | 1130 | static int initialize_cpsch(struct device_queue_manager *dqm) |
---|
1041 | 1131 | { |
---|
| 1132 | + uint64_t num_sdma_queues; |
---|
| 1133 | + uint64_t num_xgmi_sdma_queues; |
---|
| 1134 | + |
---|
1042 | 1135 | pr_debug("num of pipes: %d\n", get_pipes_per_mec(dqm)); |
---|
1043 | 1136 | |
---|
1044 | 1137 | mutex_init(&dqm->lock_hidden); |
---|
1045 | 1138 | INIT_LIST_HEAD(&dqm->queues); |
---|
1046 | | - dqm->queue_count = dqm->processes_count = 0; |
---|
1047 | | - dqm->sdma_queue_count = 0; |
---|
| 1139 | + dqm->active_queue_count = dqm->processes_count = 0; |
---|
| 1140 | + dqm->active_cp_queue_count = 0; |
---|
| 1141 | + dqm->gws_queue_count = 0; |
---|
1048 | 1142 | dqm->active_runlist = false; |
---|
1049 | | - dqm->sdma_bitmap = (1 << get_num_sdma_queues(dqm)) - 1; |
---|
| 1143 | + |
---|
| 1144 | + num_sdma_queues = get_num_sdma_queues(dqm); |
---|
| 1145 | + if (num_sdma_queues >= BITS_PER_TYPE(dqm->sdma_bitmap)) |
---|
| 1146 | + dqm->sdma_bitmap = ULLONG_MAX; |
---|
| 1147 | + else |
---|
| 1148 | + dqm->sdma_bitmap = (BIT_ULL(num_sdma_queues) - 1); |
---|
| 1149 | + |
---|
| 1150 | + num_xgmi_sdma_queues = get_num_xgmi_sdma_queues(dqm); |
---|
| 1151 | + if (num_xgmi_sdma_queues >= BITS_PER_TYPE(dqm->xgmi_sdma_bitmap)) |
---|
| 1152 | + dqm->xgmi_sdma_bitmap = ULLONG_MAX; |
---|
| 1153 | + else |
---|
| 1154 | + dqm->xgmi_sdma_bitmap = (BIT_ULL(num_xgmi_sdma_queues) - 1); |
---|
1050 | 1155 | |
---|
1051 | 1156 | INIT_WORK(&dqm->hw_exception_work, kfd_process_hw_exception); |
---|
1052 | 1157 | |
---|
.. | .. |
---|
1076 | 1181 | if (retval) |
---|
1077 | 1182 | goto fail_allocate_vidmem; |
---|
1078 | 1183 | |
---|
1079 | | - dqm->fence_addr = dqm->fence_mem->cpu_ptr; |
---|
| 1184 | + dqm->fence_addr = (uint64_t *)dqm->fence_mem->cpu_ptr; |
---|
1080 | 1185 | dqm->fence_gpu_addr = dqm->fence_mem->gpu_addr; |
---|
1081 | 1186 | |
---|
1082 | 1187 | init_interrupts(dqm); |
---|
.. | .. |
---|
1084 | 1189 | dqm_lock(dqm); |
---|
1085 | 1190 | /* clear hang status when driver try to start the hw scheduler */ |
---|
1086 | 1191 | dqm->is_hws_hang = false; |
---|
| 1192 | + dqm->is_resetting = false; |
---|
| 1193 | + dqm->sched_running = true; |
---|
1087 | 1194 | execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
---|
1088 | 1195 | dqm_unlock(dqm); |
---|
1089 | 1196 | |
---|
1090 | 1197 | return 0; |
---|
1091 | 1198 | fail_allocate_vidmem: |
---|
1092 | 1199 | fail_set_sched_resources: |
---|
1093 | | - pm_uninit(&dqm->packets); |
---|
| 1200 | + pm_uninit(&dqm->packets, false); |
---|
1094 | 1201 | fail_packet_manager_init: |
---|
1095 | 1202 | return retval; |
---|
1096 | 1203 | } |
---|
1097 | 1204 | |
---|
1098 | 1205 | static int stop_cpsch(struct device_queue_manager *dqm) |
---|
1099 | 1206 | { |
---|
| 1207 | + bool hanging; |
---|
| 1208 | + |
---|
1100 | 1209 | dqm_lock(dqm); |
---|
1101 | | - unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
---|
| 1210 | + if (!dqm->sched_running) { |
---|
| 1211 | + dqm_unlock(dqm); |
---|
| 1212 | + return 0; |
---|
| 1213 | + } |
---|
| 1214 | + |
---|
| 1215 | + if (!dqm->is_hws_hang) |
---|
| 1216 | + unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
---|
| 1217 | + hanging = dqm->is_hws_hang || dqm->is_resetting; |
---|
| 1218 | + dqm->sched_running = false; |
---|
1102 | 1219 | dqm_unlock(dqm); |
---|
1103 | 1220 | |
---|
1104 | 1221 | pm_release_ib(&dqm->packets); |
---|
1105 | 1222 | |
---|
1106 | 1223 | kfd_gtt_sa_free(dqm->dev, dqm->fence_mem); |
---|
1107 | | - pm_uninit(&dqm->packets); |
---|
| 1224 | + pm_uninit(&dqm->packets, hanging); |
---|
1108 | 1225 | |
---|
1109 | 1226 | return 0; |
---|
1110 | 1227 | } |
---|
.. | .. |
---|
1130 | 1247 | dqm->total_queue_count); |
---|
1131 | 1248 | |
---|
1132 | 1249 | list_add(&kq->list, &qpd->priv_queue_list); |
---|
1133 | | - dqm->queue_count++; |
---|
| 1250 | + increment_queue_count(dqm, qpd, kq->queue); |
---|
1134 | 1251 | qpd->is_debug = true; |
---|
1135 | 1252 | execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
---|
1136 | 1253 | dqm_unlock(dqm); |
---|
.. | .. |
---|
1144 | 1261 | { |
---|
1145 | 1262 | dqm_lock(dqm); |
---|
1146 | 1263 | list_del(&kq->list); |
---|
1147 | | - dqm->queue_count--; |
---|
| 1264 | + decrement_queue_count(dqm, qpd, kq->queue); |
---|
1148 | 1265 | qpd->is_debug = false; |
---|
1149 | 1266 | execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); |
---|
1150 | 1267 | /* |
---|
.. | .. |
---|
1163 | 1280 | int retval; |
---|
1164 | 1281 | struct mqd_manager *mqd_mgr; |
---|
1165 | 1282 | |
---|
1166 | | - retval = 0; |
---|
1167 | | - |
---|
1168 | | - dqm_lock(dqm); |
---|
1169 | | - |
---|
1170 | 1283 | if (dqm->total_queue_count >= max_num_of_queues_per_device) { |
---|
1171 | 1284 | pr_warn("Can't create new usermode queue because %d queues were already created\n", |
---|
1172 | 1285 | dqm->total_queue_count); |
---|
1173 | 1286 | retval = -EPERM; |
---|
1174 | | - goto out_unlock; |
---|
| 1287 | + goto out; |
---|
1175 | 1288 | } |
---|
1176 | 1289 | |
---|
1177 | | - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { |
---|
1178 | | - retval = allocate_sdma_queue(dqm, &q->sdma_id); |
---|
| 1290 | + if (q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 1291 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { |
---|
| 1292 | + dqm_lock(dqm); |
---|
| 1293 | + retval = allocate_sdma_queue(dqm, q); |
---|
| 1294 | + dqm_unlock(dqm); |
---|
1179 | 1295 | if (retval) |
---|
1180 | | - goto out_unlock; |
---|
1181 | | - q->properties.sdma_queue_id = |
---|
1182 | | - q->sdma_id / get_num_sdma_engines(dqm); |
---|
1183 | | - q->properties.sdma_engine_id = |
---|
1184 | | - q->sdma_id % get_num_sdma_engines(dqm); |
---|
| 1296 | + goto out; |
---|
1185 | 1297 | } |
---|
1186 | 1298 | |
---|
1187 | 1299 | retval = allocate_doorbell(qpd, q); |
---|
1188 | 1300 | if (retval) |
---|
1189 | 1301 | goto out_deallocate_sdma_queue; |
---|
1190 | 1302 | |
---|
1191 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, |
---|
1192 | | - get_mqd_type_from_queue_type(q->properties.type)); |
---|
| 1303 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 1304 | + q->properties.type)]; |
---|
1193 | 1305 | |
---|
1194 | | - if (!mqd_mgr) { |
---|
| 1306 | + if (q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 1307 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) |
---|
| 1308 | + dqm->asic_ops.init_sdma_vm(dqm, q, qpd); |
---|
| 1309 | + q->properties.tba_addr = qpd->tba_addr; |
---|
| 1310 | + q->properties.tma_addr = qpd->tma_addr; |
---|
| 1311 | + q->mqd_mem_obj = mqd_mgr->allocate_mqd(mqd_mgr->dev, &q->properties); |
---|
| 1312 | + if (!q->mqd_mem_obj) { |
---|
1195 | 1313 | retval = -ENOMEM; |
---|
1196 | 1314 | goto out_deallocate_doorbell; |
---|
1197 | 1315 | } |
---|
| 1316 | + |
---|
| 1317 | + dqm_lock(dqm); |
---|
1198 | 1318 | /* |
---|
1199 | | - * Eviction state logic: we only mark active queues as evicted |
---|
1200 | | - * to avoid the overhead of restoring inactive queues later |
---|
| 1319 | + * Eviction state logic: mark all queues as evicted, even ones |
---|
| 1320 | + * not currently active. Restoring inactive queues later only |
---|
| 1321 | + * updates the is_evicted flag but is a no-op otherwise. |
---|
1201 | 1322 | */ |
---|
1202 | | - if (qpd->evicted) |
---|
1203 | | - q->properties.is_evicted = (q->properties.queue_size > 0 && |
---|
1204 | | - q->properties.queue_percent > 0 && |
---|
1205 | | - q->properties.queue_address != 0); |
---|
1206 | | - |
---|
1207 | | - dqm->asic_ops.init_sdma_vm(dqm, q, qpd); |
---|
1208 | | - |
---|
1209 | | - q->properties.tba_addr = qpd->tba_addr; |
---|
1210 | | - q->properties.tma_addr = qpd->tma_addr; |
---|
1211 | | - retval = mqd_mgr->init_mqd(mqd_mgr, &q->mqd, &q->mqd_mem_obj, |
---|
| 1323 | + q->properties.is_evicted = !!qpd->evicted; |
---|
| 1324 | + mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, |
---|
1212 | 1325 | &q->gart_mqd_addr, &q->properties); |
---|
1213 | | - if (retval) |
---|
1214 | | - goto out_deallocate_doorbell; |
---|
1215 | 1326 | |
---|
1216 | 1327 | list_add(&q->list, &qpd->queues_list); |
---|
1217 | 1328 | qpd->queue_count++; |
---|
| 1329 | + |
---|
1218 | 1330 | if (q->properties.is_active) { |
---|
1219 | | - dqm->queue_count++; |
---|
1220 | | - retval = execute_queues_cpsch(dqm, |
---|
| 1331 | + increment_queue_count(dqm, qpd, q); |
---|
| 1332 | + |
---|
| 1333 | + execute_queues_cpsch(dqm, |
---|
1221 | 1334 | KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
---|
1222 | 1335 | } |
---|
1223 | 1336 | |
---|
1224 | | - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) |
---|
1225 | | - dqm->sdma_queue_count++; |
---|
1226 | 1337 | /* |
---|
1227 | 1338 | * Unconditionally increment this counter, regardless of the queue's |
---|
1228 | 1339 | * type or whether the queue is active. |
---|
.. | .. |
---|
1238 | 1349 | out_deallocate_doorbell: |
---|
1239 | 1350 | deallocate_doorbell(qpd, q); |
---|
1240 | 1351 | out_deallocate_sdma_queue: |
---|
1241 | | - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) |
---|
1242 | | - deallocate_sdma_queue(dqm, q->sdma_id); |
---|
1243 | | -out_unlock: |
---|
1244 | | - dqm_unlock(dqm); |
---|
1245 | | - |
---|
| 1352 | + if (q->properties.type == KFD_QUEUE_TYPE_SDMA || |
---|
| 1353 | + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { |
---|
| 1354 | + dqm_lock(dqm); |
---|
| 1355 | + deallocate_sdma_queue(dqm, q); |
---|
| 1356 | + dqm_unlock(dqm); |
---|
| 1357 | + } |
---|
| 1358 | +out: |
---|
1246 | 1359 | return retval; |
---|
1247 | 1360 | } |
---|
1248 | 1361 | |
---|
1249 | | -int amdkfd_fence_wait_timeout(unsigned int *fence_addr, |
---|
1250 | | - unsigned int fence_value, |
---|
| 1362 | +int amdkfd_fence_wait_timeout(uint64_t *fence_addr, |
---|
| 1363 | + uint64_t fence_value, |
---|
1251 | 1364 | unsigned int timeout_ms) |
---|
1252 | 1365 | { |
---|
1253 | 1366 | unsigned long end_jiffies = msecs_to_jiffies(timeout_ms) + jiffies; |
---|
.. | .. |
---|
1270 | 1383 | return 0; |
---|
1271 | 1384 | } |
---|
1272 | 1385 | |
---|
1273 | | -static int unmap_sdma_queues(struct device_queue_manager *dqm) |
---|
1274 | | -{ |
---|
1275 | | - int i, retval = 0; |
---|
1276 | | - |
---|
1277 | | - for (i = 0; i < dqm->dev->device_info->num_sdma_engines; i++) { |
---|
1278 | | - retval = pm_send_unmap_queue(&dqm->packets, KFD_QUEUE_TYPE_SDMA, |
---|
1279 | | - KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0, false, i); |
---|
1280 | | - if (retval) |
---|
1281 | | - return retval; |
---|
1282 | | - } |
---|
1283 | | - return retval; |
---|
1284 | | -} |
---|
1285 | | - |
---|
1286 | 1386 | /* dqm->lock mutex has to be locked before calling this function */ |
---|
1287 | 1387 | static int map_queues_cpsch(struct device_queue_manager *dqm) |
---|
1288 | 1388 | { |
---|
1289 | 1389 | int retval; |
---|
1290 | 1390 | |
---|
1291 | | - if (dqm->queue_count <= 0 || dqm->processes_count <= 0) |
---|
| 1391 | + if (!dqm->sched_running) |
---|
1292 | 1392 | return 0; |
---|
1293 | | - |
---|
| 1393 | + if (dqm->active_queue_count <= 0 || dqm->processes_count <= 0) |
---|
| 1394 | + return 0; |
---|
1294 | 1395 | if (dqm->active_runlist) |
---|
1295 | 1396 | return 0; |
---|
1296 | 1397 | |
---|
1297 | 1398 | retval = pm_send_runlist(&dqm->packets, &dqm->queues); |
---|
| 1399 | + pr_debug("%s sent runlist\n", __func__); |
---|
1298 | 1400 | if (retval) { |
---|
1299 | 1401 | pr_err("failed to execute runlist\n"); |
---|
1300 | 1402 | return retval; |
---|
.. | .. |
---|
1311 | 1413 | { |
---|
1312 | 1414 | int retval = 0; |
---|
1313 | 1415 | |
---|
| 1416 | + if (!dqm->sched_running) |
---|
| 1417 | + return 0; |
---|
1314 | 1418 | if (dqm->is_hws_hang) |
---|
1315 | 1419 | return -EIO; |
---|
1316 | 1420 | if (!dqm->active_runlist) |
---|
1317 | 1421 | return retval; |
---|
1318 | | - |
---|
1319 | | - pr_debug("Before destroying queues, sdma queue count is : %u\n", |
---|
1320 | | - dqm->sdma_queue_count); |
---|
1321 | | - |
---|
1322 | | - if (dqm->sdma_queue_count > 0) |
---|
1323 | | - unmap_sdma_queues(dqm); |
---|
1324 | 1422 | |
---|
1325 | 1423 | retval = pm_send_unmap_queue(&dqm->packets, KFD_QUEUE_TYPE_COMPUTE, |
---|
1326 | 1424 | filter, filter_param, false, 0); |
---|
.. | .. |
---|
1332 | 1430 | KFD_FENCE_COMPLETED); |
---|
1333 | 1431 | /* should be timed out */ |
---|
1334 | 1432 | retval = amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED, |
---|
1335 | | - QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS); |
---|
1336 | | - if (retval) |
---|
| 1433 | + queue_preemption_timeout_ms); |
---|
| 1434 | + if (retval) { |
---|
| 1435 | + pr_err("The cp might be in an unrecoverable state due to an unsuccessful queues preemption\n"); |
---|
| 1436 | + dqm->is_hws_hang = true; |
---|
| 1437 | + /* It's possible we're detecting a HWS hang in the |
---|
| 1438 | + * middle of a GPU reset. No need to schedule another |
---|
| 1439 | + * reset in this case. |
---|
| 1440 | + */ |
---|
| 1441 | + if (!dqm->is_resetting) |
---|
| 1442 | + schedule_work(&dqm->hw_exception_work); |
---|
1337 | 1443 | return retval; |
---|
| 1444 | + } |
---|
1338 | 1445 | |
---|
1339 | 1446 | pm_release_ib(&dqm->packets); |
---|
1340 | 1447 | dqm->active_runlist = false; |
---|
.. | .. |
---|
1352 | 1459 | if (dqm->is_hws_hang) |
---|
1353 | 1460 | return -EIO; |
---|
1354 | 1461 | retval = unmap_queues_cpsch(dqm, filter, filter_param); |
---|
1355 | | - if (retval) { |
---|
1356 | | - pr_err("The cp might be in an unrecoverable state due to an unsuccessful queues preemption\n"); |
---|
1357 | | - dqm->is_hws_hang = true; |
---|
1358 | | - schedule_work(&dqm->hw_exception_work); |
---|
| 1462 | + if (retval) |
---|
1359 | 1463 | return retval; |
---|
1360 | | - } |
---|
1361 | 1464 | |
---|
1362 | 1465 | return map_queues_cpsch(dqm); |
---|
1363 | 1466 | } |
---|
.. | .. |
---|
1368 | 1471 | { |
---|
1369 | 1472 | int retval; |
---|
1370 | 1473 | struct mqd_manager *mqd_mgr; |
---|
1371 | | - bool preempt_all_queues; |
---|
| 1474 | + uint64_t sdma_val = 0; |
---|
| 1475 | + struct kfd_process_device *pdd = qpd_to_pdd(qpd); |
---|
1372 | 1476 | |
---|
1373 | | - preempt_all_queues = false; |
---|
| 1477 | + /* Get the SDMA queue stats */ |
---|
| 1478 | + if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || |
---|
| 1479 | + (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { |
---|
| 1480 | + retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr, |
---|
| 1481 | + &sdma_val); |
---|
| 1482 | + if (retval) |
---|
| 1483 | + pr_err("Failed to read SDMA queue counter for queue: %d\n", |
---|
| 1484 | + q->properties.queue_id); |
---|
| 1485 | + } |
---|
1374 | 1486 | |
---|
1375 | 1487 | retval = 0; |
---|
1376 | 1488 | |
---|
.. | .. |
---|
1387 | 1499 | |
---|
1388 | 1500 | } |
---|
1389 | 1501 | |
---|
1390 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, |
---|
1391 | | - get_mqd_type_from_queue_type(q->properties.type)); |
---|
1392 | | - if (!mqd_mgr) { |
---|
1393 | | - retval = -ENOMEM; |
---|
1394 | | - goto failed; |
---|
1395 | | - } |
---|
| 1502 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 1503 | + q->properties.type)]; |
---|
1396 | 1504 | |
---|
1397 | 1505 | deallocate_doorbell(qpd, q); |
---|
1398 | 1506 | |
---|
1399 | | - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { |
---|
1400 | | - dqm->sdma_queue_count--; |
---|
1401 | | - deallocate_sdma_queue(dqm, q->sdma_id); |
---|
| 1507 | + if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || |
---|
| 1508 | + (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { |
---|
| 1509 | + deallocate_sdma_queue(dqm, q); |
---|
| 1510 | + pdd->sdma_past_activity_counter += sdma_val; |
---|
1402 | 1511 | } |
---|
1403 | 1512 | |
---|
1404 | 1513 | list_del(&q->list); |
---|
1405 | 1514 | qpd->queue_count--; |
---|
1406 | 1515 | if (q->properties.is_active) { |
---|
1407 | | - dqm->queue_count--; |
---|
| 1516 | + decrement_queue_count(dqm, qpd, q); |
---|
1408 | 1517 | retval = execute_queues_cpsch(dqm, |
---|
1409 | 1518 | KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); |
---|
1410 | 1519 | if (retval == -ETIME) |
---|
1411 | 1520 | qpd->reset_wavefronts = true; |
---|
1412 | 1521 | } |
---|
1413 | | - |
---|
1414 | | - mqd_mgr->uninit_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
1415 | 1522 | |
---|
1416 | 1523 | /* |
---|
1417 | 1524 | * Unconditionally decrement this counter, regardless of the queue's |
---|
.. | .. |
---|
1423 | 1530 | |
---|
1424 | 1531 | dqm_unlock(dqm); |
---|
1425 | 1532 | |
---|
| 1533 | + /* Do free_mqd after dqm_unlock(dqm) to avoid circular locking */ |
---|
| 1534 | + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
| 1535 | + |
---|
1426 | 1536 | return retval; |
---|
1427 | 1537 | |
---|
1428 | | -failed: |
---|
1429 | 1538 | failed_try_destroy_debugged_queue: |
---|
1430 | 1539 | |
---|
1431 | 1540 | dqm_unlock(dqm); |
---|
.. | .. |
---|
1525 | 1634 | static int process_termination_nocpsch(struct device_queue_manager *dqm, |
---|
1526 | 1635 | struct qcm_process_device *qpd) |
---|
1527 | 1636 | { |
---|
1528 | | - struct queue *q, *next; |
---|
| 1637 | + struct queue *q; |
---|
1529 | 1638 | struct device_process_node *cur, *next_dpn; |
---|
1530 | 1639 | int retval = 0; |
---|
| 1640 | + bool found = false; |
---|
1531 | 1641 | |
---|
1532 | 1642 | dqm_lock(dqm); |
---|
1533 | 1643 | |
---|
1534 | 1644 | /* Clear all user mode queues */ |
---|
1535 | | - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { |
---|
| 1645 | + while (!list_empty(&qpd->queues_list)) { |
---|
| 1646 | + struct mqd_manager *mqd_mgr; |
---|
1536 | 1647 | int ret; |
---|
1537 | 1648 | |
---|
| 1649 | + q = list_first_entry(&qpd->queues_list, struct queue, list); |
---|
| 1650 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 1651 | + q->properties.type)]; |
---|
1538 | 1652 | ret = destroy_queue_nocpsch_locked(dqm, qpd, q); |
---|
1539 | 1653 | if (ret) |
---|
1540 | 1654 | retval = ret; |
---|
| 1655 | + dqm_unlock(dqm); |
---|
| 1656 | + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
| 1657 | + dqm_lock(dqm); |
---|
1541 | 1658 | } |
---|
1542 | 1659 | |
---|
1543 | 1660 | /* Unregister process */ |
---|
.. | .. |
---|
1546 | 1663 | list_del(&cur->list); |
---|
1547 | 1664 | kfree(cur); |
---|
1548 | 1665 | dqm->processes_count--; |
---|
| 1666 | + found = true; |
---|
1549 | 1667 | break; |
---|
1550 | 1668 | } |
---|
1551 | 1669 | } |
---|
1552 | 1670 | |
---|
1553 | 1671 | dqm_unlock(dqm); |
---|
| 1672 | + |
---|
| 1673 | + /* Outside the DQM lock because under the DQM lock we can't do |
---|
| 1674 | + * reclaim or take other locks that others hold while reclaiming. |
---|
| 1675 | + */ |
---|
| 1676 | + if (found) |
---|
| 1677 | + kfd_dec_compute_active(dqm->dev); |
---|
| 1678 | + |
---|
1554 | 1679 | return retval; |
---|
1555 | 1680 | } |
---|
1556 | 1681 | |
---|
| 1682 | +static int get_wave_state(struct device_queue_manager *dqm, |
---|
| 1683 | + struct queue *q, |
---|
| 1684 | + void __user *ctl_stack, |
---|
| 1685 | + u32 *ctl_stack_used_size, |
---|
| 1686 | + u32 *save_area_used_size) |
---|
| 1687 | +{ |
---|
| 1688 | + struct mqd_manager *mqd_mgr; |
---|
| 1689 | + |
---|
| 1690 | + dqm_lock(dqm); |
---|
| 1691 | + |
---|
| 1692 | + mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP]; |
---|
| 1693 | + |
---|
| 1694 | + if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || |
---|
| 1695 | + q->properties.is_active || !q->device->cwsr_enabled || |
---|
| 1696 | + !mqd_mgr->get_wave_state) { |
---|
| 1697 | + dqm_unlock(dqm); |
---|
| 1698 | + return -EINVAL; |
---|
| 1699 | + } |
---|
| 1700 | + |
---|
| 1701 | + dqm_unlock(dqm); |
---|
| 1702 | + |
---|
| 1703 | + /* |
---|
| 1704 | + * get_wave_state is outside the dqm lock to prevent circular locking |
---|
| 1705 | + * and the queue should be protected against destruction by the process |
---|
| 1706 | + * lock. |
---|
| 1707 | + */ |
---|
| 1708 | + return mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, |
---|
| 1709 | + ctl_stack_used_size, save_area_used_size); |
---|
| 1710 | +} |
---|
1557 | 1711 | |
---|
1558 | 1712 | static int process_termination_cpsch(struct device_queue_manager *dqm, |
---|
1559 | 1713 | struct qcm_process_device *qpd) |
---|
1560 | 1714 | { |
---|
1561 | 1715 | int retval; |
---|
1562 | | - struct queue *q, *next; |
---|
| 1716 | + struct queue *q; |
---|
1563 | 1717 | struct kernel_queue *kq, *kq_next; |
---|
1564 | 1718 | struct mqd_manager *mqd_mgr; |
---|
1565 | 1719 | struct device_process_node *cur, *next_dpn; |
---|
1566 | 1720 | enum kfd_unmap_queues_filter filter = |
---|
1567 | 1721 | KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES; |
---|
| 1722 | + bool found = false; |
---|
1568 | 1723 | |
---|
1569 | 1724 | retval = 0; |
---|
1570 | 1725 | |
---|
.. | .. |
---|
1573 | 1728 | /* Clean all kernel queues */ |
---|
1574 | 1729 | list_for_each_entry_safe(kq, kq_next, &qpd->priv_queue_list, list) { |
---|
1575 | 1730 | list_del(&kq->list); |
---|
1576 | | - dqm->queue_count--; |
---|
| 1731 | + decrement_queue_count(dqm, qpd, kq->queue); |
---|
1577 | 1732 | qpd->is_debug = false; |
---|
1578 | 1733 | dqm->total_queue_count--; |
---|
1579 | 1734 | filter = KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES; |
---|
.. | .. |
---|
1581 | 1736 | |
---|
1582 | 1737 | /* Clear all user mode queues */ |
---|
1583 | 1738 | list_for_each_entry(q, &qpd->queues_list, list) { |
---|
1584 | | - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { |
---|
1585 | | - dqm->sdma_queue_count--; |
---|
1586 | | - deallocate_sdma_queue(dqm, q->sdma_id); |
---|
1587 | | - } |
---|
| 1739 | + if (q->properties.type == KFD_QUEUE_TYPE_SDMA) |
---|
| 1740 | + deallocate_sdma_queue(dqm, q); |
---|
| 1741 | + else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) |
---|
| 1742 | + deallocate_sdma_queue(dqm, q); |
---|
1588 | 1743 | |
---|
1589 | 1744 | if (q->properties.is_active) |
---|
1590 | | - dqm->queue_count--; |
---|
| 1745 | + decrement_queue_count(dqm, qpd, q); |
---|
1591 | 1746 | |
---|
1592 | 1747 | dqm->total_queue_count--; |
---|
1593 | 1748 | } |
---|
.. | .. |
---|
1598 | 1753 | list_del(&cur->list); |
---|
1599 | 1754 | kfree(cur); |
---|
1600 | 1755 | dqm->processes_count--; |
---|
| 1756 | + found = true; |
---|
1601 | 1757 | break; |
---|
1602 | 1758 | } |
---|
1603 | 1759 | } |
---|
.. | .. |
---|
1609 | 1765 | qpd->reset_wavefronts = false; |
---|
1610 | 1766 | } |
---|
1611 | 1767 | |
---|
1612 | | - /* lastly, free mqd resources */ |
---|
1613 | | - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { |
---|
1614 | | - mqd_mgr = dqm->ops.get_mqd_manager(dqm, |
---|
1615 | | - get_mqd_type_from_queue_type(q->properties.type)); |
---|
1616 | | - if (!mqd_mgr) { |
---|
1617 | | - retval = -ENOMEM; |
---|
1618 | | - goto out; |
---|
1619 | | - } |
---|
| 1768 | + /* Lastly, free mqd resources. |
---|
| 1769 | + * Do free_mqd() after dqm_unlock to avoid circular locking. |
---|
| 1770 | + */ |
---|
| 1771 | + while (!list_empty(&qpd->queues_list)) { |
---|
| 1772 | + q = list_first_entry(&qpd->queues_list, struct queue, list); |
---|
| 1773 | + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( |
---|
| 1774 | + q->properties.type)]; |
---|
1620 | 1775 | list_del(&q->list); |
---|
1621 | 1776 | qpd->queue_count--; |
---|
1622 | | - mqd_mgr->uninit_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
| 1777 | + dqm_unlock(dqm); |
---|
| 1778 | + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); |
---|
| 1779 | + dqm_lock(dqm); |
---|
| 1780 | + } |
---|
| 1781 | + dqm_unlock(dqm); |
---|
| 1782 | + |
---|
| 1783 | + /* Outside the DQM lock because under the DQM lock we can't do |
---|
| 1784 | + * reclaim or take other locks that others hold while reclaiming. |
---|
| 1785 | + */ |
---|
| 1786 | + if (found) |
---|
| 1787 | + kfd_dec_compute_active(dqm->dev); |
---|
| 1788 | + |
---|
| 1789 | + return retval; |
---|
| 1790 | +} |
---|
| 1791 | + |
---|
| 1792 | +static int init_mqd_managers(struct device_queue_manager *dqm) |
---|
| 1793 | +{ |
---|
| 1794 | + int i, j; |
---|
| 1795 | + struct mqd_manager *mqd_mgr; |
---|
| 1796 | + |
---|
| 1797 | + for (i = 0; i < KFD_MQD_TYPE_MAX; i++) { |
---|
| 1798 | + mqd_mgr = dqm->asic_ops.mqd_manager_init(i, dqm->dev); |
---|
| 1799 | + if (!mqd_mgr) { |
---|
| 1800 | + pr_err("mqd manager [%d] initialization failed\n", i); |
---|
| 1801 | + goto out_free; |
---|
| 1802 | + } |
---|
| 1803 | + dqm->mqd_mgrs[i] = mqd_mgr; |
---|
1623 | 1804 | } |
---|
1624 | 1805 | |
---|
1625 | | -out: |
---|
1626 | | - dqm_unlock(dqm); |
---|
| 1806 | + return 0; |
---|
| 1807 | + |
---|
| 1808 | +out_free: |
---|
| 1809 | + for (j = 0; j < i; j++) { |
---|
| 1810 | + kfree(dqm->mqd_mgrs[j]); |
---|
| 1811 | + dqm->mqd_mgrs[j] = NULL; |
---|
| 1812 | + } |
---|
| 1813 | + |
---|
| 1814 | + return -ENOMEM; |
---|
| 1815 | +} |
---|
| 1816 | + |
---|
| 1817 | +/* Allocate one hiq mqd (HWS) and all SDMA mqd in a continuous trunk*/ |
---|
| 1818 | +static int allocate_hiq_sdma_mqd(struct device_queue_manager *dqm) |
---|
| 1819 | +{ |
---|
| 1820 | + int retval; |
---|
| 1821 | + struct kfd_dev *dev = dqm->dev; |
---|
| 1822 | + struct kfd_mem_obj *mem_obj = &dqm->hiq_sdma_mqd; |
---|
| 1823 | + uint32_t size = dqm->mqd_mgrs[KFD_MQD_TYPE_SDMA]->mqd_size * |
---|
| 1824 | + get_num_all_sdma_engines(dqm) * |
---|
| 1825 | + dev->device_info->num_sdma_queues_per_engine + |
---|
| 1826 | + dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size; |
---|
| 1827 | + |
---|
| 1828 | + retval = amdgpu_amdkfd_alloc_gtt_mem(dev->kgd, size, |
---|
| 1829 | + &(mem_obj->gtt_mem), &(mem_obj->gpu_addr), |
---|
| 1830 | + (void *)&(mem_obj->cpu_ptr), false); |
---|
| 1831 | + |
---|
1627 | 1832 | return retval; |
---|
1628 | 1833 | } |
---|
1629 | 1834 | |
---|
.. | .. |
---|
1662 | 1867 | dqm->ops.initialize = initialize_cpsch; |
---|
1663 | 1868 | dqm->ops.start = start_cpsch; |
---|
1664 | 1869 | dqm->ops.stop = stop_cpsch; |
---|
| 1870 | + dqm->ops.pre_reset = pre_reset; |
---|
1665 | 1871 | dqm->ops.destroy_queue = destroy_queue_cpsch; |
---|
1666 | 1872 | dqm->ops.update_queue = update_queue; |
---|
1667 | | - dqm->ops.get_mqd_manager = get_mqd_manager; |
---|
1668 | 1873 | dqm->ops.register_process = register_process; |
---|
1669 | 1874 | dqm->ops.unregister_process = unregister_process; |
---|
1670 | 1875 | dqm->ops.uninitialize = uninitialize; |
---|
.. | .. |
---|
1675 | 1880 | dqm->ops.process_termination = process_termination_cpsch; |
---|
1676 | 1881 | dqm->ops.evict_process_queues = evict_process_queues_cpsch; |
---|
1677 | 1882 | dqm->ops.restore_process_queues = restore_process_queues_cpsch; |
---|
| 1883 | + dqm->ops.get_wave_state = get_wave_state; |
---|
1678 | 1884 | break; |
---|
1679 | 1885 | case KFD_SCHED_POLICY_NO_HWS: |
---|
1680 | 1886 | /* initialize dqm for no cp scheduling */ |
---|
1681 | 1887 | dqm->ops.start = start_nocpsch; |
---|
1682 | 1888 | dqm->ops.stop = stop_nocpsch; |
---|
| 1889 | + dqm->ops.pre_reset = pre_reset; |
---|
1683 | 1890 | dqm->ops.create_queue = create_queue_nocpsch; |
---|
1684 | 1891 | dqm->ops.destroy_queue = destroy_queue_nocpsch; |
---|
1685 | 1892 | dqm->ops.update_queue = update_queue; |
---|
1686 | | - dqm->ops.get_mqd_manager = get_mqd_manager; |
---|
1687 | 1893 | dqm->ops.register_process = register_process; |
---|
1688 | 1894 | dqm->ops.unregister_process = unregister_process; |
---|
1689 | 1895 | dqm->ops.initialize = initialize_nocpsch; |
---|
.. | .. |
---|
1694 | 1900 | dqm->ops.evict_process_queues = evict_process_queues_nocpsch; |
---|
1695 | 1901 | dqm->ops.restore_process_queues = |
---|
1696 | 1902 | restore_process_queues_nocpsch; |
---|
| 1903 | + dqm->ops.get_wave_state = get_wave_state; |
---|
1697 | 1904 | break; |
---|
1698 | 1905 | default: |
---|
1699 | 1906 | pr_err("Invalid scheduling policy %d\n", dqm->sched_policy); |
---|
.. | .. |
---|
1717 | 1924 | case CHIP_FIJI: |
---|
1718 | 1925 | case CHIP_POLARIS10: |
---|
1719 | 1926 | case CHIP_POLARIS11: |
---|
| 1927 | + case CHIP_POLARIS12: |
---|
| 1928 | + case CHIP_VEGAM: |
---|
1720 | 1929 | device_queue_manager_init_vi_tonga(&dqm->asic_ops); |
---|
1721 | 1930 | break; |
---|
1722 | 1931 | |
---|
1723 | 1932 | case CHIP_VEGA10: |
---|
| 1933 | + case CHIP_VEGA12: |
---|
| 1934 | + case CHIP_VEGA20: |
---|
1724 | 1935 | case CHIP_RAVEN: |
---|
| 1936 | + case CHIP_RENOIR: |
---|
| 1937 | + case CHIP_ARCTURUS: |
---|
1725 | 1938 | device_queue_manager_init_v9(&dqm->asic_ops); |
---|
| 1939 | + break; |
---|
| 1940 | + case CHIP_NAVI10: |
---|
| 1941 | + case CHIP_NAVI12: |
---|
| 1942 | + case CHIP_NAVI14: |
---|
| 1943 | + case CHIP_SIENNA_CICHLID: |
---|
| 1944 | + case CHIP_NAVY_FLOUNDER: |
---|
| 1945 | + device_queue_manager_init_v10_navi10(&dqm->asic_ops); |
---|
1726 | 1946 | break; |
---|
1727 | 1947 | default: |
---|
1728 | 1948 | WARN(1, "Unexpected ASIC family %u", |
---|
1729 | 1949 | dev->device_info->asic_family); |
---|
| 1950 | + goto out_free; |
---|
| 1951 | + } |
---|
| 1952 | + |
---|
| 1953 | + if (init_mqd_managers(dqm)) |
---|
| 1954 | + goto out_free; |
---|
| 1955 | + |
---|
| 1956 | + if (allocate_hiq_sdma_mqd(dqm)) { |
---|
| 1957 | + pr_err("Failed to allocate hiq sdma mqd trunk buffer\n"); |
---|
1730 | 1958 | goto out_free; |
---|
1731 | 1959 | } |
---|
1732 | 1960 | |
---|
.. | .. |
---|
1738 | 1966 | return NULL; |
---|
1739 | 1967 | } |
---|
1740 | 1968 | |
---|
| 1969 | +static void deallocate_hiq_sdma_mqd(struct kfd_dev *dev, |
---|
| 1970 | + struct kfd_mem_obj *mqd) |
---|
| 1971 | +{ |
---|
| 1972 | + WARN(!mqd, "No hiq sdma mqd trunk to free"); |
---|
| 1973 | + |
---|
| 1974 | + amdgpu_amdkfd_free_gtt_mem(dev->kgd, mqd->gtt_mem); |
---|
| 1975 | +} |
---|
| 1976 | + |
---|
1741 | 1977 | void device_queue_manager_uninit(struct device_queue_manager *dqm) |
---|
1742 | 1978 | { |
---|
1743 | 1979 | dqm->ops.uninitialize(dqm); |
---|
| 1980 | + deallocate_hiq_sdma_mqd(dqm->dev, &dqm->hiq_sdma_mqd); |
---|
1744 | 1981 | kfree(dqm); |
---|
1745 | 1982 | } |
---|
1746 | 1983 | |
---|
1747 | | -int kfd_process_vm_fault(struct device_queue_manager *dqm, |
---|
1748 | | - unsigned int pasid) |
---|
| 1984 | +int kfd_process_vm_fault(struct device_queue_manager *dqm, u32 pasid) |
---|
1749 | 1985 | { |
---|
1750 | 1986 | struct kfd_process_device *pdd; |
---|
1751 | 1987 | struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); |
---|
.. | .. |
---|
1753 | 1989 | |
---|
1754 | 1990 | if (!p) |
---|
1755 | 1991 | return -EINVAL; |
---|
| 1992 | + WARN(debug_evictions, "Evicting pid %d", p->lead_thread->pid); |
---|
1756 | 1993 | pdd = kfd_get_process_device_data(dqm->dev, p); |
---|
1757 | 1994 | if (pdd) |
---|
1758 | 1995 | ret = dqm->ops.evict_process_queues(dqm, &pdd->qpd); |
---|
.. | .. |
---|
1765 | 2002 | { |
---|
1766 | 2003 | struct device_queue_manager *dqm = container_of(work, |
---|
1767 | 2004 | struct device_queue_manager, hw_exception_work); |
---|
1768 | | - dqm->dev->kfd2kgd->gpu_recover(dqm->dev->kgd); |
---|
| 2005 | + amdgpu_amdkfd_gpu_reset(dqm->dev->kgd); |
---|
1769 | 2006 | } |
---|
1770 | 2007 | |
---|
1771 | 2008 | #if defined(CONFIG_DEBUG_FS) |
---|
.. | .. |
---|
1798 | 2035 | int pipe, queue; |
---|
1799 | 2036 | int r = 0; |
---|
1800 | 2037 | |
---|
| 2038 | + if (!dqm->sched_running) { |
---|
| 2039 | + seq_printf(m, " Device is stopped\n"); |
---|
| 2040 | + |
---|
| 2041 | + return 0; |
---|
| 2042 | + } |
---|
| 2043 | + |
---|
1801 | 2044 | r = dqm->dev->kfd2kgd->hqd_dump(dqm->dev->kgd, |
---|
1802 | | - KFD_CIK_HIQ_PIPE, KFD_CIK_HIQ_QUEUE, &dump, &n_regs); |
---|
| 2045 | + KFD_CIK_HIQ_PIPE, KFD_CIK_HIQ_QUEUE, |
---|
| 2046 | + &dump, &n_regs); |
---|
1803 | 2047 | if (!r) { |
---|
1804 | 2048 | seq_printf(m, " HIQ on MEC %d Pipe %d Queue %d\n", |
---|
1805 | | - KFD_CIK_HIQ_PIPE/get_pipes_per_mec(dqm)+1, |
---|
1806 | | - KFD_CIK_HIQ_PIPE%get_pipes_per_mec(dqm), |
---|
1807 | | - KFD_CIK_HIQ_QUEUE); |
---|
| 2049 | + KFD_CIK_HIQ_PIPE/get_pipes_per_mec(dqm)+1, |
---|
| 2050 | + KFD_CIK_HIQ_PIPE%get_pipes_per_mec(dqm), |
---|
| 2051 | + KFD_CIK_HIQ_QUEUE); |
---|
1808 | 2052 | seq_reg_dump(m, dump, n_regs); |
---|
1809 | 2053 | |
---|
1810 | 2054 | kfree(dump); |
---|
.. | .. |
---|
1815 | 2059 | |
---|
1816 | 2060 | for (queue = 0; queue < get_queues_per_pipe(dqm); queue++) { |
---|
1817 | 2061 | if (!test_bit(pipe_offset + queue, |
---|
1818 | | - dqm->dev->shared_resources.queue_bitmap)) |
---|
| 2062 | + dqm->dev->shared_resources.cp_queue_bitmap)) |
---|
1819 | 2063 | continue; |
---|
1820 | 2064 | |
---|
1821 | 2065 | r = dqm->dev->kfd2kgd->hqd_dump( |
---|
.. | .. |
---|
1831 | 2075 | } |
---|
1832 | 2076 | } |
---|
1833 | 2077 | |
---|
1834 | | - for (pipe = 0; pipe < get_num_sdma_engines(dqm); pipe++) { |
---|
1835 | | - for (queue = 0; queue < KFD_SDMA_QUEUES_PER_ENGINE; queue++) { |
---|
| 2078 | + for (pipe = 0; pipe < get_num_all_sdma_engines(dqm); pipe++) { |
---|
| 2079 | + for (queue = 0; |
---|
| 2080 | + queue < dqm->dev->device_info->num_sdma_queues_per_engine; |
---|
| 2081 | + queue++) { |
---|
1836 | 2082 | r = dqm->dev->kfd2kgd->hqd_sdma_dump( |
---|
1837 | 2083 | dqm->dev->kgd, pipe, queue, &dump, &n_regs); |
---|
1838 | 2084 | if (r) |
---|