.. | .. |
---|
26 | 26 | #include "kfd_device_queue_manager.h" |
---|
27 | 27 | #include "kfd_priv.h" |
---|
28 | 28 | #include "kfd_kernel_queue.h" |
---|
| 29 | +#include "amdgpu_amdkfd.h" |
---|
29 | 30 | |
---|
30 | 31 | static inline struct process_queue_node *get_queue_by_qid( |
---|
31 | 32 | struct process_queue_manager *pqm, unsigned int qid) |
---|
.. | .. |
---|
52 | 53 | pr_debug("The new slot id %lu\n", found); |
---|
53 | 54 | |
---|
54 | 55 | if (found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) { |
---|
55 | | - pr_info("Cannot open more queues for process with pasid %d\n", |
---|
| 56 | + pr_info("Cannot open more queues for process with pasid 0x%x\n", |
---|
56 | 57 | pqm->process->pasid); |
---|
57 | 58 | return -ENOMEM; |
---|
58 | 59 | } |
---|
.. | .. |
---|
72 | 73 | |
---|
73 | 74 | dev->dqm->ops.process_termination(dev->dqm, &pdd->qpd); |
---|
74 | 75 | pdd->already_dequeued = true; |
---|
| 76 | +} |
---|
| 77 | + |
---|
| 78 | +int pqm_set_gws(struct process_queue_manager *pqm, unsigned int qid, |
---|
| 79 | + void *gws) |
---|
| 80 | +{ |
---|
| 81 | + struct kfd_dev *dev = NULL; |
---|
| 82 | + struct process_queue_node *pqn; |
---|
| 83 | + struct kfd_process_device *pdd; |
---|
| 84 | + struct kgd_mem *mem = NULL; |
---|
| 85 | + int ret; |
---|
| 86 | + |
---|
| 87 | + pqn = get_queue_by_qid(pqm, qid); |
---|
| 88 | + if (!pqn) { |
---|
| 89 | + pr_err("Queue id does not match any known queue\n"); |
---|
| 90 | + return -EINVAL; |
---|
| 91 | + } |
---|
| 92 | + |
---|
| 93 | + if (pqn->q) |
---|
| 94 | + dev = pqn->q->device; |
---|
| 95 | + if (WARN_ON(!dev)) |
---|
| 96 | + return -ENODEV; |
---|
| 97 | + |
---|
| 98 | + pdd = kfd_get_process_device_data(dev, pqm->process); |
---|
| 99 | + if (!pdd) { |
---|
| 100 | + pr_err("Process device data doesn't exist\n"); |
---|
| 101 | + return -EINVAL; |
---|
| 102 | + } |
---|
| 103 | + |
---|
| 104 | + /* Only allow one queue per process can have GWS assigned */ |
---|
| 105 | + if (gws && pdd->qpd.num_gws) |
---|
| 106 | + return -EBUSY; |
---|
| 107 | + |
---|
| 108 | + if (!gws && pdd->qpd.num_gws == 0) |
---|
| 109 | + return -EINVAL; |
---|
| 110 | + |
---|
| 111 | + if (gws) |
---|
| 112 | + ret = amdgpu_amdkfd_add_gws_to_process(pdd->process->kgd_process_info, |
---|
| 113 | + gws, &mem); |
---|
| 114 | + else |
---|
| 115 | + ret = amdgpu_amdkfd_remove_gws_from_process(pdd->process->kgd_process_info, |
---|
| 116 | + pqn->q->gws); |
---|
| 117 | + if (unlikely(ret)) |
---|
| 118 | + return ret; |
---|
| 119 | + |
---|
| 120 | + pqn->q->gws = mem; |
---|
| 121 | + pdd->qpd.num_gws = gws ? amdgpu_amdkfd_get_num_gws(dev->kgd) : 0; |
---|
| 122 | + |
---|
| 123 | + return pqn->q->device->dqm->ops.update_queue(pqn->q->device->dqm, |
---|
| 124 | + pqn->q); |
---|
75 | 125 | } |
---|
76 | 126 | |
---|
77 | 127 | void kfd_process_dequeue_from_all_devices(struct kfd_process *p) |
---|
.. | .. |
---|
100 | 150 | struct process_queue_node *pqn, *next; |
---|
101 | 151 | |
---|
102 | 152 | list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) { |
---|
| 153 | + if (pqn->q && pqn->q->gws) |
---|
| 154 | + amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, |
---|
| 155 | + pqn->q->gws); |
---|
| 156 | + kfd_procfs_del_queue(pqn->q); |
---|
103 | 157 | uninit_queue(pqn->q); |
---|
104 | 158 | list_del(&pqn->process_queue_list); |
---|
105 | 159 | kfree(pqn); |
---|
.. | .. |
---|
109 | 163 | pqm->queue_slot_bitmap = NULL; |
---|
110 | 164 | } |
---|
111 | 165 | |
---|
112 | | -static int create_cp_queue(struct process_queue_manager *pqm, |
---|
| 166 | +static int init_user_queue(struct process_queue_manager *pqm, |
---|
113 | 167 | struct kfd_dev *dev, struct queue **q, |
---|
114 | 168 | struct queue_properties *q_properties, |
---|
115 | 169 | struct file *f, unsigned int qid) |
---|
.. | .. |
---|
139 | 193 | struct kfd_dev *dev, |
---|
140 | 194 | struct file *f, |
---|
141 | 195 | struct queue_properties *properties, |
---|
142 | | - unsigned int *qid) |
---|
| 196 | + unsigned int *qid, |
---|
| 197 | + uint32_t *p_doorbell_offset_in_process) |
---|
143 | 198 | { |
---|
144 | 199 | int retval; |
---|
145 | 200 | struct kfd_process_device *pdd; |
---|
.. | .. |
---|
186 | 241 | |
---|
187 | 242 | switch (type) { |
---|
188 | 243 | case KFD_QUEUE_TYPE_SDMA: |
---|
189 | | - if (dev->dqm->queue_count >= get_num_sdma_queues(dev->dqm)) { |
---|
190 | | - pr_err("Over-subscription is not allowed for SDMA.\n"); |
---|
191 | | - retval = -EPERM; |
---|
192 | | - goto err_create_queue; |
---|
193 | | - } |
---|
194 | | - |
---|
195 | | - retval = create_cp_queue(pqm, dev, &q, properties, f, *qid); |
---|
| 244 | + case KFD_QUEUE_TYPE_SDMA_XGMI: |
---|
| 245 | + /* SDMA queues are always allocated statically no matter |
---|
| 246 | + * which scheduler mode is used. We also do not need to |
---|
| 247 | + * check whether a SDMA queue can be allocated here, because |
---|
| 248 | + * allocate_sdma_queue() in create_queue() has the |
---|
| 249 | + * corresponding check logic. |
---|
| 250 | + */ |
---|
| 251 | + retval = init_user_queue(pqm, dev, &q, properties, f, *qid); |
---|
196 | 252 | if (retval != 0) |
---|
197 | 253 | goto err_create_queue; |
---|
198 | 254 | pqn->q = q; |
---|
199 | 255 | pqn->kq = NULL; |
---|
200 | 256 | retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd); |
---|
201 | | - pr_debug("DQM returned %d for create_queue\n", retval); |
---|
202 | 257 | print_queue(q); |
---|
203 | 258 | break; |
---|
204 | 259 | |
---|
.. | .. |
---|
207 | 262 | if ((dev->dqm->sched_policy == |
---|
208 | 263 | KFD_SCHED_POLICY_HWS_NO_OVERSUBSCRIPTION) && |
---|
209 | 264 | ((dev->dqm->processes_count >= dev->vm_info.vmid_num_kfd) || |
---|
210 | | - (dev->dqm->queue_count >= get_queues_num(dev->dqm)))) { |
---|
| 265 | + (dev->dqm->active_queue_count >= get_cp_queues_num(dev->dqm)))) { |
---|
211 | 266 | pr_debug("Over-subscription is not allowed when amdkfd.sched_policy == 1\n"); |
---|
212 | 267 | retval = -EPERM; |
---|
213 | 268 | goto err_create_queue; |
---|
214 | 269 | } |
---|
215 | 270 | |
---|
216 | | - retval = create_cp_queue(pqm, dev, &q, properties, f, *qid); |
---|
| 271 | + retval = init_user_queue(pqm, dev, &q, properties, f, *qid); |
---|
217 | 272 | if (retval != 0) |
---|
218 | 273 | goto err_create_queue; |
---|
219 | 274 | pqn->q = q; |
---|
220 | 275 | pqn->kq = NULL; |
---|
221 | 276 | retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd); |
---|
222 | | - pr_debug("DQM returned %d for create_queue\n", retval); |
---|
223 | 277 | print_queue(q); |
---|
224 | 278 | break; |
---|
225 | 279 | case KFD_QUEUE_TYPE_DIQ: |
---|
.. | .. |
---|
240 | 294 | } |
---|
241 | 295 | |
---|
242 | 296 | if (retval != 0) { |
---|
243 | | - pr_err("Pasid %d DQM create queue %d failed. ret %d\n", |
---|
| 297 | + pr_err("Pasid 0x%x DQM create queue type %d failed. ret %d\n", |
---|
244 | 298 | pqm->process->pasid, type, retval); |
---|
245 | 299 | goto err_create_queue; |
---|
246 | 300 | } |
---|
247 | 301 | |
---|
248 | | - if (q) |
---|
| 302 | + if (q && p_doorbell_offset_in_process) |
---|
249 | 303 | /* Return the doorbell offset within the doorbell page |
---|
250 | 304 | * to the caller so it can be passed up to user mode |
---|
251 | 305 | * (in bytes). |
---|
| 306 | + * There are always 1024 doorbells per process, so in case |
---|
| 307 | + * of 8-byte doorbells, there are two doorbell pages per |
---|
| 308 | + * process. |
---|
252 | 309 | */ |
---|
253 | | - properties->doorbell_off = |
---|
| 310 | + *p_doorbell_offset_in_process = |
---|
254 | 311 | (q->properties.doorbell_off * sizeof(uint32_t)) & |
---|
255 | 312 | (kfd_doorbell_process_slice(dev) - 1); |
---|
256 | 313 | |
---|
.. | .. |
---|
260 | 317 | |
---|
261 | 318 | if (q) { |
---|
262 | 319 | pr_debug("PQM done creating queue\n"); |
---|
| 320 | + kfd_procfs_add_queue(q); |
---|
263 | 321 | print_queue_properties(&q->properties); |
---|
264 | 322 | } |
---|
265 | 323 | |
---|
266 | 324 | return retval; |
---|
267 | 325 | |
---|
268 | 326 | err_create_queue: |
---|
| 327 | + uninit_queue(q); |
---|
| 328 | + if (kq) |
---|
| 329 | + kernel_queue_uninit(kq, false); |
---|
269 | 330 | kfree(pqn); |
---|
270 | 331 | err_allocate_pqn: |
---|
271 | 332 | /* check if queues list is empty unregister process from device */ |
---|
.. | .. |
---|
312 | 373 | /* destroy kernel queue (DIQ) */ |
---|
313 | 374 | dqm = pqn->kq->dev->dqm; |
---|
314 | 375 | dqm->ops.destroy_kernel_queue(dqm, pqn->kq, &pdd->qpd); |
---|
315 | | - kernel_queue_uninit(pqn->kq); |
---|
| 376 | + kernel_queue_uninit(pqn->kq, false); |
---|
316 | 377 | } |
---|
317 | 378 | |
---|
318 | 379 | if (pqn->q) { |
---|
| 380 | + kfd_procfs_del_queue(pqn->q); |
---|
319 | 381 | dqm = pqn->q->device->dqm; |
---|
320 | 382 | retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q); |
---|
321 | 383 | if (retval) { |
---|
322 | | - pr_err("Pasid %d destroy queue %d failed, ret %d\n", |
---|
| 384 | + pr_err("Pasid 0x%x destroy queue %d failed, ret %d\n", |
---|
323 | 385 | pqm->process->pasid, |
---|
324 | 386 | pqn->q->properties.queue_id, retval); |
---|
325 | 387 | if (retval != -ETIME) |
---|
326 | 388 | goto err_destroy_queue; |
---|
327 | 389 | } |
---|
| 390 | + |
---|
| 391 | + if (pqn->q->gws) { |
---|
| 392 | + amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, |
---|
| 393 | + pqn->q->gws); |
---|
| 394 | + pdd->qpd.num_gws = 0; |
---|
| 395 | + } |
---|
| 396 | + |
---|
328 | 397 | kfree(pqn->q->properties.cu_mask); |
---|
329 | 398 | pqn->q->properties.cu_mask = NULL; |
---|
330 | 399 | uninit_queue(pqn->q); |
---|
.. | .. |
---|
408 | 477 | return NULL; |
---|
409 | 478 | } |
---|
410 | 479 | |
---|
| 480 | +struct queue *pqm_get_user_queue(struct process_queue_manager *pqm, |
---|
| 481 | + unsigned int qid) |
---|
| 482 | +{ |
---|
| 483 | + struct process_queue_node *pqn; |
---|
| 484 | + |
---|
| 485 | + pqn = get_queue_by_qid(pqm, qid); |
---|
| 486 | + return pqn ? pqn->q : NULL; |
---|
| 487 | +} |
---|
| 488 | + |
---|
| 489 | +int pqm_get_wave_state(struct process_queue_manager *pqm, |
---|
| 490 | + unsigned int qid, |
---|
| 491 | + void __user *ctl_stack, |
---|
| 492 | + u32 *ctl_stack_used_size, |
---|
| 493 | + u32 *save_area_used_size) |
---|
| 494 | +{ |
---|
| 495 | + struct process_queue_node *pqn; |
---|
| 496 | + |
---|
| 497 | + pqn = get_queue_by_qid(pqm, qid); |
---|
| 498 | + if (!pqn) { |
---|
| 499 | + pr_debug("amdkfd: No queue %d exists for operation\n", |
---|
| 500 | + qid); |
---|
| 501 | + return -EFAULT; |
---|
| 502 | + } |
---|
| 503 | + |
---|
| 504 | + return pqn->q->device->dqm->ops.get_wave_state(pqn->q->device->dqm, |
---|
| 505 | + pqn->q, |
---|
| 506 | + ctl_stack, |
---|
| 507 | + ctl_stack_used_size, |
---|
| 508 | + save_area_used_size); |
---|
| 509 | +} |
---|
| 510 | + |
---|
411 | 511 | #if defined(CONFIG_DEBUG_FS) |
---|
412 | 512 | |
---|
413 | 513 | int pqm_debugfs_mqds(struct seq_file *m, void *data) |
---|
.. | .. |
---|
424 | 524 | q = pqn->q; |
---|
425 | 525 | switch (q->properties.type) { |
---|
426 | 526 | case KFD_QUEUE_TYPE_SDMA: |
---|
| 527 | + case KFD_QUEUE_TYPE_SDMA_XGMI: |
---|
427 | 528 | seq_printf(m, " SDMA queue on device %x\n", |
---|
428 | 529 | q->device->id); |
---|
429 | 530 | mqd_type = KFD_MQD_TYPE_SDMA; |
---|
.. | .. |
---|
439 | 540 | q->properties.type, q->device->id); |
---|
440 | 541 | continue; |
---|
441 | 542 | } |
---|
442 | | - mqd_mgr = q->device->dqm->ops.get_mqd_manager( |
---|
443 | | - q->device->dqm, mqd_type); |
---|
| 543 | + mqd_mgr = q->device->dqm->mqd_mgrs[mqd_type]; |
---|
444 | 544 | } else if (pqn->kq) { |
---|
445 | 545 | q = pqn->kq->queue; |
---|
446 | 546 | mqd_mgr = pqn->kq->mqd_mgr; |
---|
.. | .. |
---|
448 | 548 | case KFD_QUEUE_TYPE_DIQ: |
---|
449 | 549 | seq_printf(m, " DIQ on device %x\n", |
---|
450 | 550 | pqn->kq->dev->id); |
---|
451 | | - mqd_type = KFD_MQD_TYPE_HIQ; |
---|
452 | 551 | break; |
---|
453 | 552 | default: |
---|
454 | 553 | seq_printf(m, |
---|