drm/amdkfd: Walk through list with dqm lock hold
authorjsg <jsg@openbsd.org>
Mon, 19 Jul 2021 10:33:03 +0000 (10:33 +0000)
committerjsg <jsg@openbsd.org>
Mon, 19 Jul 2021 10:33:03 +0000 (10:33 +0000)
From xinhui pan
4cd713e48c272a80af935424afaa607ea125aed4 in linux 5.10.y/5.10.51
56f221b6389e7ab99c30bbf01c71998ae92fc584 in mainline linux

sys/dev/pci/drm/amd/amdkfd/kfd_device_queue_manager.c

index ffb3d37..352a32d 100644 (file)
@@ -1712,7 +1712,7 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
                struct qcm_process_device *qpd)
 {
        int retval;
-       struct queue *q, *next;
+       struct queue *q;
        struct kernel_queue *kq, *kq_next;
        struct mqd_manager *mqd_mgr;
        struct device_process_node *cur, *next_dpn;
@@ -1769,24 +1769,26 @@ static int process_termination_cpsch(struct device_queue_manager *dqm,
                qpd->reset_wavefronts = false;
        }
 
-       dqm_unlock(dqm);
-
-       /* Outside the DQM lock because under the DQM lock we can't do
-        * reclaim or take other locks that others hold while reclaiming.
-        */
-       if (found)
-               kfd_dec_compute_active(dqm->dev);
-
        /* Lastly, free mqd resources.
         * Do free_mqd() after dqm_unlock to avoid circular locking.
         */
-       list_for_each_entry_safe(q, next, &qpd->queues_list, list) {
+       while (!list_empty(&qpd->queues_list)) {
+               q = list_first_entry(&qpd->queues_list, struct queue, list);
                mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
                                q->properties.type)];
                list_del(&q->list);
                qpd->queue_count--;
+               dqm_unlock(dqm);
                mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj);
+               dqm_lock(dqm);
        }
+       dqm_unlock(dqm);
+
+       /* Outside the DQM lock because under the DQM lock we can't do
+        * reclaim or take other locks that others hold while reclaiming.
+        */
+       if (found)
+               kfd_dec_compute_active(dqm->dev);
 
        return retval;
 }