162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2022 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci#include "amdgpu.h"
2462306a36Sopenharmony_ci#include "amdgpu_xcp.h"
2562306a36Sopenharmony_ci#include "amdgpu_drv.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <drm/drm_drv.h>
2862306a36Sopenharmony_ci#include "../amdxcp/amdgpu_xcp_drv.h"
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic int __amdgpu_xcp_run(struct amdgpu_xcp_mgr *xcp_mgr,
3162306a36Sopenharmony_ci			    struct amdgpu_xcp_ip *xcp_ip, int xcp_state)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	int (*run_func)(void *handle, uint32_t inst_mask);
3462306a36Sopenharmony_ci	int ret = 0;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	if (!xcp_ip || !xcp_ip->valid || !xcp_ip->ip_funcs)
3762306a36Sopenharmony_ci		return 0;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	run_func = NULL;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	switch (xcp_state) {
4262306a36Sopenharmony_ci	case AMDGPU_XCP_PREPARE_SUSPEND:
4362306a36Sopenharmony_ci		run_func = xcp_ip->ip_funcs->prepare_suspend;
4462306a36Sopenharmony_ci		break;
4562306a36Sopenharmony_ci	case AMDGPU_XCP_SUSPEND:
4662306a36Sopenharmony_ci		run_func = xcp_ip->ip_funcs->suspend;
4762306a36Sopenharmony_ci		break;
4862306a36Sopenharmony_ci	case AMDGPU_XCP_PREPARE_RESUME:
4962306a36Sopenharmony_ci		run_func = xcp_ip->ip_funcs->prepare_resume;
5062306a36Sopenharmony_ci		break;
5162306a36Sopenharmony_ci	case AMDGPU_XCP_RESUME:
5262306a36Sopenharmony_ci		run_func = xcp_ip->ip_funcs->resume;
5362306a36Sopenharmony_ci		break;
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	if (run_func)
5762306a36Sopenharmony_ci		ret = run_func(xcp_mgr->adev, xcp_ip->inst_mask);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	return ret;
6062306a36Sopenharmony_ci}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic int amdgpu_xcp_run_transition(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id,
6362306a36Sopenharmony_ci				     int state)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct amdgpu_xcp_ip *xcp_ip;
6662306a36Sopenharmony_ci	struct amdgpu_xcp *xcp;
6762306a36Sopenharmony_ci	int i, ret;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	if (xcp_id >= MAX_XCP || !xcp_mgr->xcp[xcp_id].valid)
7062306a36Sopenharmony_ci		return -EINVAL;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	xcp = &xcp_mgr->xcp[xcp_id];
7362306a36Sopenharmony_ci	for (i = 0; i < AMDGPU_XCP_MAX_BLOCKS; ++i) {
7462306a36Sopenharmony_ci		xcp_ip = &xcp->ip[i];
7562306a36Sopenharmony_ci		ret = __amdgpu_xcp_run(xcp_mgr, xcp_ip, state);
7662306a36Sopenharmony_ci		if (ret)
7762306a36Sopenharmony_ci			break;
7862306a36Sopenharmony_ci	}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	return ret;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciint amdgpu_xcp_prepare_suspend(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	return amdgpu_xcp_run_transition(xcp_mgr, xcp_id,
8662306a36Sopenharmony_ci					 AMDGPU_XCP_PREPARE_SUSPEND);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ciint amdgpu_xcp_suspend(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	return amdgpu_xcp_run_transition(xcp_mgr, xcp_id, AMDGPU_XCP_SUSPEND);
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ciint amdgpu_xcp_prepare_resume(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	return amdgpu_xcp_run_transition(xcp_mgr, xcp_id,
9762306a36Sopenharmony_ci					 AMDGPU_XCP_PREPARE_RESUME);
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciint amdgpu_xcp_resume(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	return amdgpu_xcp_run_transition(xcp_mgr, xcp_id, AMDGPU_XCP_RESUME);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic void __amdgpu_xcp_add_block(struct amdgpu_xcp_mgr *xcp_mgr, int xcp_id,
10662306a36Sopenharmony_ci				   struct amdgpu_xcp_ip *ip)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	struct amdgpu_xcp *xcp;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	if (!ip)
11162306a36Sopenharmony_ci		return;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	xcp = &xcp_mgr->xcp[xcp_id];
11462306a36Sopenharmony_ci	xcp->ip[ip->ip_id] = *ip;
11562306a36Sopenharmony_ci	xcp->ip[ip->ip_id].valid = true;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	xcp->valid = true;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciint amdgpu_xcp_init(struct amdgpu_xcp_mgr *xcp_mgr, int num_xcps, int mode)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct amdgpu_device *adev = xcp_mgr->adev;
12362306a36Sopenharmony_ci	struct amdgpu_xcp_ip ip;
12462306a36Sopenharmony_ci	uint8_t mem_id;
12562306a36Sopenharmony_ci	int i, j, ret;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (!num_xcps || num_xcps > MAX_XCP)
12862306a36Sopenharmony_ci		return -EINVAL;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	xcp_mgr->mode = mode;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	for (i = 0; i < MAX_XCP; ++i)
13362306a36Sopenharmony_ci		xcp_mgr->xcp[i].valid = false;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* This is needed for figuring out memory id of xcp */
13662306a36Sopenharmony_ci	xcp_mgr->num_xcp_per_mem_partition = num_xcps / xcp_mgr->adev->gmc.num_mem_partitions;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	for (i = 0; i < num_xcps; ++i) {
13962306a36Sopenharmony_ci		for (j = AMDGPU_XCP_GFXHUB; j < AMDGPU_XCP_MAX_BLOCKS; ++j) {
14062306a36Sopenharmony_ci			ret = xcp_mgr->funcs->get_ip_details(xcp_mgr, i, j,
14162306a36Sopenharmony_ci							     &ip);
14262306a36Sopenharmony_ci			if (ret)
14362306a36Sopenharmony_ci				continue;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci			__amdgpu_xcp_add_block(xcp_mgr, i, &ip);
14662306a36Sopenharmony_ci		}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci		xcp_mgr->xcp[i].id = i;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci		if (xcp_mgr->funcs->get_xcp_mem_id) {
15162306a36Sopenharmony_ci			ret = xcp_mgr->funcs->get_xcp_mem_id(
15262306a36Sopenharmony_ci				xcp_mgr, &xcp_mgr->xcp[i], &mem_id);
15362306a36Sopenharmony_ci			if (ret)
15462306a36Sopenharmony_ci				continue;
15562306a36Sopenharmony_ci			else
15662306a36Sopenharmony_ci				xcp_mgr->xcp[i].mem_id = mem_id;
15762306a36Sopenharmony_ci		}
15862306a36Sopenharmony_ci	}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	xcp_mgr->num_xcps = num_xcps;
16162306a36Sopenharmony_ci	amdgpu_xcp_update_partition_sched_list(adev);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	return 0;
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ciint amdgpu_xcp_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, int mode)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	int ret, curr_mode, num_xcps = 0;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	if (!xcp_mgr || mode == AMDGPU_XCP_MODE_NONE)
17162306a36Sopenharmony_ci		return -EINVAL;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	if (xcp_mgr->mode == mode)
17462306a36Sopenharmony_ci		return 0;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (!xcp_mgr->funcs || !xcp_mgr->funcs->switch_partition_mode)
17762306a36Sopenharmony_ci		return 0;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	mutex_lock(&xcp_mgr->xcp_lock);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	curr_mode = xcp_mgr->mode;
18262306a36Sopenharmony_ci	/* State set to transient mode */
18362306a36Sopenharmony_ci	xcp_mgr->mode = AMDGPU_XCP_MODE_TRANS;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	ret = xcp_mgr->funcs->switch_partition_mode(xcp_mgr, mode, &num_xcps);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	if (ret) {
18862306a36Sopenharmony_ci		/* Failed, get whatever mode it's at now */
18962306a36Sopenharmony_ci		if (xcp_mgr->funcs->query_partition_mode)
19062306a36Sopenharmony_ci			xcp_mgr->mode = amdgpu_xcp_query_partition_mode(
19162306a36Sopenharmony_ci				xcp_mgr, AMDGPU_XCP_FL_LOCKED);
19262306a36Sopenharmony_ci		else
19362306a36Sopenharmony_ci			xcp_mgr->mode = curr_mode;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		goto out;
19662306a36Sopenharmony_ci	}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ciout:
19962306a36Sopenharmony_ci	mutex_unlock(&xcp_mgr->xcp_lock);
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	return ret;
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ciint amdgpu_xcp_query_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr, u32 flags)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	int mode;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
20962306a36Sopenharmony_ci		return xcp_mgr->mode;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	if (!xcp_mgr->funcs || !xcp_mgr->funcs->query_partition_mode)
21262306a36Sopenharmony_ci		return xcp_mgr->mode;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	if (!(flags & AMDGPU_XCP_FL_LOCKED))
21562306a36Sopenharmony_ci		mutex_lock(&xcp_mgr->xcp_lock);
21662306a36Sopenharmony_ci	mode = xcp_mgr->funcs->query_partition_mode(xcp_mgr);
21762306a36Sopenharmony_ci	if (xcp_mgr->mode != AMDGPU_XCP_MODE_TRANS && mode != xcp_mgr->mode)
21862306a36Sopenharmony_ci		dev_WARN(
21962306a36Sopenharmony_ci			xcp_mgr->adev->dev,
22062306a36Sopenharmony_ci			"Cached partition mode %d not matching with device mode %d",
22162306a36Sopenharmony_ci			xcp_mgr->mode, mode);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	if (!(flags & AMDGPU_XCP_FL_LOCKED))
22462306a36Sopenharmony_ci		mutex_unlock(&xcp_mgr->xcp_lock);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	return mode;
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic int amdgpu_xcp_dev_alloc(struct amdgpu_device *adev)
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	struct drm_device *p_ddev;
23262306a36Sopenharmony_ci	struct drm_device *ddev;
23362306a36Sopenharmony_ci	int i, ret;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	ddev = adev_to_drm(adev);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* xcp #0 shares drm device setting with adev */
23862306a36Sopenharmony_ci	adev->xcp_mgr->xcp->ddev = ddev;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	for (i = 1; i < MAX_XCP; i++) {
24162306a36Sopenharmony_ci		ret = amdgpu_xcp_drm_dev_alloc(&p_ddev);
24262306a36Sopenharmony_ci		if (ret == -ENOSPC) {
24362306a36Sopenharmony_ci			dev_warn(adev->dev,
24462306a36Sopenharmony_ci			"Skip xcp node #%d when out of drm node resource.", i);
24562306a36Sopenharmony_ci			return 0;
24662306a36Sopenharmony_ci		} else if (ret) {
24762306a36Sopenharmony_ci			return ret;
24862306a36Sopenharmony_ci		}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci		/* Redirect all IOCTLs to the primary device */
25162306a36Sopenharmony_ci		adev->xcp_mgr->xcp[i].rdev = p_ddev->render->dev;
25262306a36Sopenharmony_ci		adev->xcp_mgr->xcp[i].pdev = p_ddev->primary->dev;
25362306a36Sopenharmony_ci		adev->xcp_mgr->xcp[i].driver = (struct drm_driver *)p_ddev->driver;
25462306a36Sopenharmony_ci		adev->xcp_mgr->xcp[i].vma_offset_manager = p_ddev->vma_offset_manager;
25562306a36Sopenharmony_ci		p_ddev->render->dev = ddev;
25662306a36Sopenharmony_ci		p_ddev->primary->dev = ddev;
25762306a36Sopenharmony_ci		p_ddev->vma_offset_manager = ddev->vma_offset_manager;
25862306a36Sopenharmony_ci		p_ddev->driver = &amdgpu_partition_driver;
25962306a36Sopenharmony_ci		adev->xcp_mgr->xcp[i].ddev = p_ddev;
26062306a36Sopenharmony_ci	}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return 0;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ciint amdgpu_xcp_mgr_init(struct amdgpu_device *adev, int init_mode,
26662306a36Sopenharmony_ci			int init_num_xcps,
26762306a36Sopenharmony_ci			struct amdgpu_xcp_mgr_funcs *xcp_funcs)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	struct amdgpu_xcp_mgr *xcp_mgr;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (!xcp_funcs || !xcp_funcs->switch_partition_mode ||
27262306a36Sopenharmony_ci	    !xcp_funcs->get_ip_details)
27362306a36Sopenharmony_ci		return -EINVAL;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	xcp_mgr = kzalloc(sizeof(*xcp_mgr), GFP_KERNEL);
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	if (!xcp_mgr)
27862306a36Sopenharmony_ci		return -ENOMEM;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	xcp_mgr->adev = adev;
28162306a36Sopenharmony_ci	xcp_mgr->funcs = xcp_funcs;
28262306a36Sopenharmony_ci	xcp_mgr->mode = init_mode;
28362306a36Sopenharmony_ci	mutex_init(&xcp_mgr->xcp_lock);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	if (init_mode != AMDGPU_XCP_MODE_NONE)
28662306a36Sopenharmony_ci		amdgpu_xcp_init(xcp_mgr, init_num_xcps, init_mode);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	adev->xcp_mgr = xcp_mgr;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return amdgpu_xcp_dev_alloc(adev);
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ciint amdgpu_xcp_get_partition(struct amdgpu_xcp_mgr *xcp_mgr,
29462306a36Sopenharmony_ci			     enum AMDGPU_XCP_IP_BLOCK ip, int instance)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	struct amdgpu_xcp *xcp;
29762306a36Sopenharmony_ci	int i, id_mask = 0;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	if (ip >= AMDGPU_XCP_MAX_BLOCKS)
30062306a36Sopenharmony_ci		return -EINVAL;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	for (i = 0; i < xcp_mgr->num_xcps; ++i) {
30362306a36Sopenharmony_ci		xcp = &xcp_mgr->xcp[i];
30462306a36Sopenharmony_ci		if ((xcp->valid) && (xcp->ip[ip].valid) &&
30562306a36Sopenharmony_ci		    (xcp->ip[ip].inst_mask & BIT(instance)))
30662306a36Sopenharmony_ci			id_mask |= BIT(i);
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	if (!id_mask)
31062306a36Sopenharmony_ci		id_mask = -ENXIO;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	return id_mask;
31362306a36Sopenharmony_ci}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ciint amdgpu_xcp_get_inst_details(struct amdgpu_xcp *xcp,
31662306a36Sopenharmony_ci				enum AMDGPU_XCP_IP_BLOCK ip,
31762306a36Sopenharmony_ci				uint32_t *inst_mask)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	if (!xcp->valid || !inst_mask || !(xcp->ip[ip].valid))
32062306a36Sopenharmony_ci		return -EINVAL;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	*inst_mask = xcp->ip[ip].inst_mask;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	return 0;
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ciint amdgpu_xcp_dev_register(struct amdgpu_device *adev,
32862306a36Sopenharmony_ci			const struct pci_device_id *ent)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	int i, ret;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	if (!adev->xcp_mgr)
33362306a36Sopenharmony_ci		return 0;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	for (i = 1; i < MAX_XCP; i++) {
33662306a36Sopenharmony_ci		if (!adev->xcp_mgr->xcp[i].ddev)
33762306a36Sopenharmony_ci			break;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci		ret = drm_dev_register(adev->xcp_mgr->xcp[i].ddev, ent->driver_data);
34062306a36Sopenharmony_ci		if (ret)
34162306a36Sopenharmony_ci			return ret;
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return 0;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_civoid amdgpu_xcp_dev_unplug(struct amdgpu_device *adev)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	struct drm_device *p_ddev;
35062306a36Sopenharmony_ci	int i;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (!adev->xcp_mgr)
35362306a36Sopenharmony_ci		return;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	for (i = 1; i < MAX_XCP; i++) {
35662306a36Sopenharmony_ci		if (!adev->xcp_mgr->xcp[i].ddev)
35762306a36Sopenharmony_ci			break;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci		p_ddev = adev->xcp_mgr->xcp[i].ddev;
36062306a36Sopenharmony_ci		drm_dev_unplug(p_ddev);
36162306a36Sopenharmony_ci		p_ddev->render->dev = adev->xcp_mgr->xcp[i].rdev;
36262306a36Sopenharmony_ci		p_ddev->primary->dev = adev->xcp_mgr->xcp[i].pdev;
36362306a36Sopenharmony_ci		p_ddev->driver =  adev->xcp_mgr->xcp[i].driver;
36462306a36Sopenharmony_ci		p_ddev->vma_offset_manager = adev->xcp_mgr->xcp[i].vma_offset_manager;
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ciint amdgpu_xcp_open_device(struct amdgpu_device *adev,
36962306a36Sopenharmony_ci			   struct amdgpu_fpriv *fpriv,
37062306a36Sopenharmony_ci			   struct drm_file *file_priv)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	int i;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	if (!adev->xcp_mgr)
37562306a36Sopenharmony_ci		return 0;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	fpriv->xcp_id = AMDGPU_XCP_NO_PARTITION;
37862306a36Sopenharmony_ci	for (i = 0; i < MAX_XCP; ++i) {
37962306a36Sopenharmony_ci		if (!adev->xcp_mgr->xcp[i].ddev)
38062306a36Sopenharmony_ci			break;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci		if (file_priv->minor == adev->xcp_mgr->xcp[i].ddev->render) {
38362306a36Sopenharmony_ci			if (adev->xcp_mgr->xcp[i].valid == FALSE) {
38462306a36Sopenharmony_ci				dev_err(adev->dev, "renderD%d partition %d not valid!",
38562306a36Sopenharmony_ci						file_priv->minor->index, i);
38662306a36Sopenharmony_ci				return -ENOENT;
38762306a36Sopenharmony_ci			}
38862306a36Sopenharmony_ci			dev_dbg(adev->dev, "renderD%d partition %d opened!",
38962306a36Sopenharmony_ci					file_priv->minor->index, i);
39062306a36Sopenharmony_ci			fpriv->xcp_id = i;
39162306a36Sopenharmony_ci			break;
39262306a36Sopenharmony_ci		}
39362306a36Sopenharmony_ci	}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	fpriv->vm.mem_id = fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION ? -1 :
39662306a36Sopenharmony_ci				adev->xcp_mgr->xcp[fpriv->xcp_id].mem_id;
39762306a36Sopenharmony_ci	return 0;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_civoid amdgpu_xcp_release_sched(struct amdgpu_device *adev,
40162306a36Sopenharmony_ci				  struct amdgpu_ctx_entity *entity)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	struct drm_gpu_scheduler *sched;
40462306a36Sopenharmony_ci	struct amdgpu_ring *ring;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	if (!adev->xcp_mgr)
40762306a36Sopenharmony_ci		return;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	sched = entity->entity.rq->sched;
41062306a36Sopenharmony_ci	if (sched->ready) {
41162306a36Sopenharmony_ci		ring = to_amdgpu_ring(entity->entity.rq->sched);
41262306a36Sopenharmony_ci		atomic_dec(&adev->xcp_mgr->xcp[ring->xcp_id].ref_cnt);
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
416