|
@@ -63,21 +63,44 @@ enum KFD_MQD_TYPE get_mqd_type_from_queue_type(enum kfd_queue_type type)
|
|
|
return KFD_MQD_TYPE_CP;
|
|
|
}
|
|
|
|
|
|
-unsigned int get_first_pipe(struct device_queue_manager *dqm)
|
|
|
+static bool is_pipe_enabled(struct device_queue_manager *dqm, int mec, int pipe)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ int pipe_offset = mec * dqm->dev->shared_resources.num_pipe_per_mec
|
|
|
+ + pipe * dqm->dev->shared_resources.num_queue_per_pipe;
|
|
|
+
|
|
|
+ /* queue is available for KFD usage if bit is 1 */
|
|
|
+ for (i = 0; i < dqm->dev->shared_resources.num_queue_per_pipe; ++i)
|
|
|
+ if (test_bit(pipe_offset + i,
|
|
|
+ dqm->dev->shared_resources.queue_bitmap))
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int get_mec_num(struct device_queue_manager *dqm)
|
|
|
{
|
|
|
BUG_ON(!dqm || !dqm->dev);
|
|
|
- return dqm->dev->shared_resources.first_compute_pipe;
|
|
|
+
|
|
|
+ return dqm->dev->shared_resources.num_mec;
|
|
|
}
|
|
|
|
|
|
-unsigned int get_pipes_num(struct device_queue_manager *dqm)
|
|
|
+unsigned int get_queues_num(struct device_queue_manager *dqm)
|
|
|
{
|
|
|
BUG_ON(!dqm || !dqm->dev);
|
|
|
- return dqm->dev->shared_resources.compute_pipe_count;
|
|
|
+ return bitmap_weight(dqm->dev->shared_resources.queue_bitmap,
|
|
|
+ KGD_MAX_QUEUES);
|
|
|
}
|
|
|
|
|
|
-static inline unsigned int get_pipes_num_cpsch(void)
|
|
|
+unsigned int get_queues_per_pipe(struct device_queue_manager *dqm)
|
|
|
{
|
|
|
- return PIPE_PER_ME_CP_SCHEDULING;
|
|
|
+ BUG_ON(!dqm || !dqm->dev);
|
|
|
+ return dqm->dev->shared_resources.num_queue_per_pipe;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int get_pipes_per_mec(struct device_queue_manager *dqm)
|
|
|
+{
|
|
|
+ BUG_ON(!dqm || !dqm->dev);
|
|
|
+ return dqm->dev->shared_resources.num_pipe_per_mec;
|
|
|
}
|
|
|
|
|
|
void program_sh_mem_settings(struct device_queue_manager *dqm,
|
|
@@ -200,12 +223,16 @@ static int allocate_hqd(struct device_queue_manager *dqm, struct queue *q)
|
|
|
|
|
|
set = false;
|
|
|
|
|
|
- for (pipe = dqm->next_pipe_to_allocate, i = 0; i < get_pipes_num(dqm);
|
|
|
- pipe = ((pipe + 1) % get_pipes_num(dqm)), ++i) {
|
|
|
+ for (pipe = dqm->next_pipe_to_allocate, i = 0; i < get_pipes_per_mec(dqm);
|
|
|
+ pipe = ((pipe + 1) % get_pipes_per_mec(dqm)), ++i) {
|
|
|
+
|
|
|
+ if (!is_pipe_enabled(dqm, 0, pipe))
|
|
|
+ continue;
|
|
|
+
|
|
|
if (dqm->allocated_queues[pipe] != 0) {
|
|
|
bit = find_first_bit(
|
|
|
(unsigned long *)&dqm->allocated_queues[pipe],
|
|
|
- QUEUES_PER_PIPE);
|
|
|
+ get_queues_per_pipe(dqm));
|
|
|
|
|
|
clear_bit(bit,
|
|
|
(unsigned long *)&dqm->allocated_queues[pipe]);
|
|
@@ -222,7 +249,7 @@ static int allocate_hqd(struct device_queue_manager *dqm, struct queue *q)
|
|
|
pr_debug("kfd: DQM %s hqd slot - pipe (%d) queue(%d)\n",
|
|
|
__func__, q->pipe, q->queue);
|
|
|
/* horizontal hqd allocation */
|
|
|
- dqm->next_pipe_to_allocate = (pipe + 1) % get_pipes_num(dqm);
|
|
|
+ dqm->next_pipe_to_allocate = (pipe + 1) % get_pipes_per_mec(dqm);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -469,36 +496,25 @@ set_pasid_vmid_mapping(struct device_queue_manager *dqm, unsigned int pasid,
|
|
|
vmid);
|
|
|
}
|
|
|
|
|
|
-int init_pipelines(struct device_queue_manager *dqm,
|
|
|
- unsigned int pipes_num, unsigned int first_pipe)
|
|
|
-{
|
|
|
- BUG_ON(!dqm || !dqm->dev);
|
|
|
-
|
|
|
- pr_debug("kfd: In func %s\n", __func__);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static void init_interrupts(struct device_queue_manager *dqm)
|
|
|
{
|
|
|
unsigned int i;
|
|
|
|
|
|
BUG_ON(dqm == NULL);
|
|
|
|
|
|
- for (i = 0 ; i < get_pipes_num(dqm) ; i++)
|
|
|
- dqm->dev->kfd2kgd->init_interrupts(dqm->dev->kgd,
|
|
|
- i + get_first_pipe(dqm));
|
|
|
+ for (i = 0 ; i < get_pipes_per_mec(dqm) ; i++)
|
|
|
+ if (is_pipe_enabled(dqm, 0, i))
|
|
|
+ dqm->dev->kfd2kgd->init_interrupts(dqm->dev->kgd, i);
|
|
|
}
|
|
|
|
|
|
static int init_scheduler(struct device_queue_manager *dqm)
|
|
|
{
|
|
|
- int retval;
|
|
|
+ int retval = 0;
|
|
|
|
|
|
BUG_ON(!dqm);
|
|
|
|
|
|
pr_debug("kfd: In %s\n", __func__);
|
|
|
|
|
|
- retval = init_pipelines(dqm, get_pipes_num(dqm), get_first_pipe(dqm));
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
@@ -509,21 +525,21 @@ static int initialize_nocpsch(struct device_queue_manager *dqm)
|
|
|
BUG_ON(!dqm);
|
|
|
|
|
|
pr_debug("kfd: In func %s num of pipes: %d\n",
|
|
|
- __func__, get_pipes_num(dqm));
|
|
|
+ __func__, get_pipes_per_mec(dqm));
|
|
|
|
|
|
mutex_init(&dqm->lock);
|
|
|
INIT_LIST_HEAD(&dqm->queues);
|
|
|
dqm->queue_count = dqm->next_pipe_to_allocate = 0;
|
|
|
dqm->sdma_queue_count = 0;
|
|
|
- dqm->allocated_queues = kcalloc(get_pipes_num(dqm),
|
|
|
+ dqm->allocated_queues = kcalloc(get_pipes_per_mec(dqm),
|
|
|
sizeof(unsigned int), GFP_KERNEL);
|
|
|
if (!dqm->allocated_queues) {
|
|
|
mutex_destroy(&dqm->lock);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- for (i = 0; i < get_pipes_num(dqm); i++)
|
|
|
- dqm->allocated_queues[i] = (1 << QUEUES_PER_PIPE) - 1;
|
|
|
+ for (i = 0; i < get_pipes_per_mec(dqm); i++)
|
|
|
+ dqm->allocated_queues[i] = (1 << get_queues_per_pipe(dqm)) - 1;
|
|
|
|
|
|
dqm->vmid_bitmap = (1 << VMID_PER_DEVICE) - 1;
|
|
|
dqm->sdma_bitmap = (1 << CIK_SDMA_QUEUES) - 1;
|
|
@@ -630,18 +646,38 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm,
|
|
|
|
|
|
static int set_sched_resources(struct device_queue_manager *dqm)
|
|
|
{
|
|
|
+ int i, mec;
|
|
|
struct scheduling_resources res;
|
|
|
- unsigned int queue_num, queue_mask;
|
|
|
|
|
|
BUG_ON(!dqm);
|
|
|
|
|
|
pr_debug("kfd: In func %s\n", __func__);
|
|
|
|
|
|
- queue_num = get_pipes_num_cpsch() * QUEUES_PER_PIPE;
|
|
|
- queue_mask = (1 << queue_num) - 1;
|
|
|
res.vmid_mask = (1 << VMID_PER_DEVICE) - 1;
|
|
|
res.vmid_mask <<= KFD_VMID_START_OFFSET;
|
|
|
- res.queue_mask = queue_mask << (get_first_pipe(dqm) * QUEUES_PER_PIPE);
|
|
|
+
|
|
|
+ res.queue_mask = 0;
|
|
|
+ for (i = 0; i < KGD_MAX_QUEUES; ++i) {
|
|
|
+ mec = (i / dqm->dev->shared_resources.num_queue_per_pipe)
|
|
|
+ / dqm->dev->shared_resources.num_pipe_per_mec;
|
|
|
+
|
|
|
+ if (!test_bit(i, dqm->dev->shared_resources.queue_bitmap))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* only acquire queues from the first MEC */
|
|
|
+ if (mec > 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* This situation may be hit in the future if a new HW
|
|
|
+ * generation exposes more than 64 queues. If so, the
|
|
|
+ * definition of res.queue_mask needs updating */
|
|
|
+ if (WARN_ON(i > (sizeof(res.queue_mask)*8))) {
|
|
|
+ pr_err("Invalid queue enabled by amdgpu: %d\n", i);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ res.queue_mask |= (1ull << i);
|
|
|
+ }
|
|
|
res.gws_mask = res.oac_mask = res.gds_heap_base =
|
|
|
res.gds_heap_size = 0;
|
|
|
|
|
@@ -660,7 +696,7 @@ static int initialize_cpsch(struct device_queue_manager *dqm)
|
|
|
BUG_ON(!dqm);
|
|
|
|
|
|
pr_debug("kfd: In func %s num of pipes: %d\n",
|
|
|
- __func__, get_pipes_num_cpsch());
|
|
|
+ __func__, get_pipes_per_mec(dqm));
|
|
|
|
|
|
mutex_init(&dqm->lock);
|
|
|
INIT_LIST_HEAD(&dqm->queues);
|