Commit 98a54e88 authored by Le Ma's avatar Le Ma Committed by Alex Deucher
Browse files

drm/amdgpu: add sysfs node for compute partition mode



Add current/available compute partitin mode sysfs node.

v2: make the sysfs node as IP independent one in amdgpu_gfx.c

Signed-off-by: default avatarLe Ma <le.ma@amd.com>
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3566938b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3634,6 +3634,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
	mutex_init(&adev->srbm_mutex);
	mutex_init(&adev->gfx.pipe_reserve_mutex);
	mutex_init(&adev->gfx.gfx_off_mutex);
	mutex_init(&adev->gfx.partition_mutex);
	mutex_init(&adev->grbm_idx_mutex);
	mutex_init(&adev->mn_lock);
	mutex_init(&adev->virt.vf_errors.lock);
+132 −0
Original line number Diff line number Diff line
@@ -1174,3 +1174,135 @@ bool amdgpu_gfx_is_master_xcc(struct amdgpu_device *adev, int xcc_id)
	return !(xcc_id % (adev->gfx.num_xcc_per_xcp ?
			adev->gfx.num_xcc_per_xcp : 1));
}

static ssize_t amdgpu_gfx_get_current_compute_partition(struct device *dev,
						struct device_attribute *addr,
						char *buf)
{
	struct drm_device *ddev = dev_get_drvdata(dev);
	struct amdgpu_device *adev = drm_to_adev(ddev);
	enum amdgpu_gfx_partition mode;
	char *partition_mode;

	mode = adev->gfx.funcs->query_partition_mode(adev);

	switch (mode) {
	case AMDGPU_SPX_PARTITION_MODE:
		partition_mode = "SPX";
		break;
	case AMDGPU_DPX_PARTITION_MODE:
		partition_mode = "DPX";
		break;
	case AMDGPU_TPX_PARTITION_MODE:
		partition_mode = "TPX";
		break;
	case AMDGPU_QPX_PARTITION_MODE:
		partition_mode = "QPX";
		break;
	case AMDGPU_CPX_PARTITION_MODE:
		partition_mode = "CPX";
		break;
	default:
		partition_mode = "UNKNOWN";
		break;
	}

	return sysfs_emit(buf, "%s\n", partition_mode);
}

static ssize_t amdgpu_gfx_set_compute_partition(struct device *dev,
						struct device_attribute *addr,
						const char *buf, size_t count)
{
	struct drm_device *ddev = dev_get_drvdata(dev);
	struct amdgpu_device *adev = drm_to_adev(ddev);
	enum amdgpu_gfx_partition mode;
	int ret;

	if (adev->gfx.num_xcd % 2 != 0)
		return -EINVAL;

	if (!strncasecmp("SPX", buf, strlen("SPX"))) {
		mode = AMDGPU_SPX_PARTITION_MODE;
	} else if (!strncasecmp("DPX", buf, strlen("DPX"))) {
		if (adev->gfx.num_xcd != 4 || adev->gfx.num_xcd != 8)
			return -EINVAL;
		mode = AMDGPU_DPX_PARTITION_MODE;
	} else if (!strncasecmp("TPX", buf, strlen("TPX"))) {
		if (adev->gfx.num_xcd != 6)
			return -EINVAL;
		mode = AMDGPU_TPX_PARTITION_MODE;
	} else if (!strncasecmp("QPX", buf, strlen("QPX"))) {
		if (adev->gfx.num_xcd != 8)
			return -EINVAL;
		mode = AMDGPU_QPX_PARTITION_MODE;
	} else if (!strncasecmp("CPX", buf, strlen("CPX"))) {
		mode = AMDGPU_CPX_PARTITION_MODE;
	} else {
		return -EINVAL;
	}

	mutex_lock(&adev->gfx.partition_mutex);

	ret = adev->gfx.funcs->switch_partition_mode(adev, mode);

	mutex_unlock(&adev->gfx.partition_mutex);

	if (ret)
		return ret;

	return count;
}

static ssize_t amdgpu_gfx_get_available_compute_partition(struct device *dev,
						struct device_attribute *addr,
						char *buf)
{
	struct drm_device *ddev = dev_get_drvdata(dev);
	struct amdgpu_device *adev = drm_to_adev(ddev);
	char *supported_partition;

	/* TBD */
	switch (adev->gfx.num_xcd) {
	case 8:
		supported_partition = "SPX, DPX, QPX, CPX";
		break;
	case 6:
		supported_partition = "SPX, TPX, CPX";
		break;
	case 4:
		supported_partition = "SPX, DPX, CPX";
		break;
	/* this seems only existing in emulation phase */
	case 2:
		supported_partition = "SPX, CPX";
		break;
	default:
		supported_partition = "Not supported";
		break;
	}

	return sysfs_emit(buf, "%s\n", supported_partition);
}

static DEVICE_ATTR(current_compute_partition, S_IRUGO | S_IWUSR,
		   amdgpu_gfx_get_current_compute_partition,
		   amdgpu_gfx_set_compute_partition);

static DEVICE_ATTR(available_compute_partition, S_IRUGO,
		   amdgpu_gfx_get_available_compute_partition, NULL);

int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev)
{
	int r;

	r = device_create_file(adev->dev, &dev_attr_current_compute_partition);
	if (r)
		return r;

	r = device_create_file(adev->dev, &dev_attr_available_compute_partition);
	if (r)
		return r;

	return 0;
}
+6 −0
Original line number Diff line number Diff line
@@ -259,6 +259,10 @@ struct amdgpu_gfx_funcs {
	void (*update_perfmon_mgcg)(struct amdgpu_device *adev, bool enable);
	int (*get_gfx_shadow_info)(struct amdgpu_device *adev,
				   struct amdgpu_gfx_shadow_info *shadow_info);
	enum amdgpu_gfx_partition
			(*query_partition_mode)(struct amdgpu_device *adev);
	int (*switch_partition_mode)(struct amdgpu_device *adev,
				     enum amdgpu_gfx_partition mode);
};

struct sq_work {
@@ -394,6 +398,7 @@ struct amdgpu_gfx {
	enum amdgpu_gfx_partition	partition_mode;
	uint32_t			num_xcd;
	uint32_t			num_xcc_per_xcp;
	struct mutex			partition_mutex;
};

#define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev))
@@ -478,4 +483,5 @@ int amdgpu_gfx_poison_consumption_handler(struct amdgpu_device *adev,
						struct amdgpu_iv_entry *entry);

bool amdgpu_gfx_is_master_xcc(struct amdgpu_device *adev, int xcc_id);
int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev);
#endif
+3 −0
Original line number Diff line number Diff line
@@ -95,6 +95,9 @@ struct amdgpu_nbio_funcs {
	void (*apply_l1_link_width_reconfig_wa)(struct amdgpu_device *adev);
	void (*clear_doorbell_interrupt)(struct amdgpu_device *adev);
	u32 (*get_rom_offset)(struct amdgpu_device *adev);
	u32 (*get_compute_partition_mode)(struct amdgpu_device *adev);
	void (*set_compute_partition_mode)(struct amdgpu_device *adev,
					   enum amdgpu_gfx_partition mode);
};

struct amdgpu_nbio {
+67 −0
Original line number Diff line number Diff line
@@ -662,6 +662,67 @@ static void gfx_v9_4_3_select_me_pipe_q(struct amdgpu_device *adev,
	soc15_grbm_select(adev, me, pipe, q, vm, 0);
}

static enum amdgpu_gfx_partition
gfx_v9_4_3_query_compute_partition(struct amdgpu_device *adev)
{
	enum amdgpu_gfx_partition mode = AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE;

	if (adev->nbio.funcs->get_compute_partition_mode)
		mode = adev->nbio.funcs->get_compute_partition_mode(adev);

	return mode;
}

static int gfx_v9_4_3_switch_compute_partition(struct amdgpu_device *adev,
						enum amdgpu_gfx_partition mode)
{
	u32 tmp = 0;
	int num_xcc_per_partition, i;

	if (mode == adev->gfx.partition_mode)
		return mode;

	switch (mode) {
	case AMDGPU_SPX_PARTITION_MODE:
		num_xcc_per_partition = adev->gfx.num_xcd;
		break;
	case AMDGPU_DPX_PARTITION_MODE:
		num_xcc_per_partition = adev->gfx.num_xcd / 2;
		break;
	case AMDGPU_TPX_PARTITION_MODE:
		num_xcc_per_partition = adev->gfx.num_xcd / 3;
		break;
	case AMDGPU_QPX_PARTITION_MODE:
		num_xcc_per_partition = adev->gfx.num_xcd / 4;
		break;
	case AMDGPU_CPX_PARTITION_MODE:
		num_xcc_per_partition = 1;
		break;
	default:
		return -EINVAL;
	}

	/* TODO:
	 * Stop user queues and threads, and make sure GPU is empty of work.
	 */

	for (i = 0; i < adev->gfx.num_xcd; i++) {
		tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, NUM_XCC_IN_XCP,
				    num_xcc_per_partition);
		tmp = REG_SET_FIELD(tmp, CP_HYP_XCP_CTL, VIRTUAL_XCC_ID,
				    i % num_xcc_per_partition);
		WREG32_SOC15(GC, i, regCP_HYP_XCP_CTL, tmp);
	}

	if (adev->nbio.funcs->set_compute_partition_mode)
		adev->nbio.funcs->set_compute_partition_mode(adev, mode);

	adev->gfx.num_xcc_per_xcp = num_xcc_per_partition;
	adev->gfx.partition_mode = mode;

	return 0;
}

static const struct amdgpu_gfx_funcs gfx_v9_4_3_gfx_funcs = {
	.get_gpu_clock_counter = &gfx_v9_4_3_get_gpu_clock_counter,
	.select_se_sh = &gfx_v9_4_3_select_se_sh,
@@ -669,6 +730,8 @@ static const struct amdgpu_gfx_funcs gfx_v9_4_3_gfx_funcs = {
	.read_wave_sgprs = &gfx_v9_4_3_read_wave_sgprs,
	.read_wave_vgprs = &gfx_v9_4_3_read_wave_vgprs,
	.select_me_pipe_q = &gfx_v9_4_3_select_me_pipe_q,
	.query_partition_mode = &gfx_v9_4_3_query_compute_partition,
	.switch_partition_mode = &gfx_v9_4_3_switch_compute_partition,
};

static int gfx_v9_4_3_gpu_early_init(struct amdgpu_device *adev)
@@ -858,6 +921,10 @@ static int gfx_v9_4_3_sw_init(void *handle)
	if (r)
		return r;

	r = amdgpu_gfx_sysfs_init(adev);
	if (r)
		return r;

	return 0;
}

Loading