Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca4b8692 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-next-4.20' of git://people.freedesktop.org/~agd5f/linux into drm-next



 Add a new list.h helper for doing bulk updates.  Used by ttm.
- Fixes for display underflow on VI APUs at 4K with UVD running
- Endian fixes for powerplay on vega
- DC fixes for interlaced video
- Vega20 powerplay fixes
- RV/RV2/PCO powerplay fixes
- Fix for spurious ACPI events on HG laptops
- Fix a memory leak in DC on driver unload
- Fixes for manual fan control mode switching
- Suspend/resume robustness fixes
- Fix display handling on RV2
- VCN fixes for DPG on PCO
- Misc code cleanups and warning fixes

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181011014739.3117-1-alexander.deucher@amd.com
parents 46972c03 df2fc43d
Loading
Loading
Loading
Loading
+21 −28
Original line number Diff line number Diff line
@@ -81,6 +81,23 @@
#include "amdgpu_bo_list.h"
#include "amdgpu_gem.h"

#define MAX_GPU_INSTANCE		16

struct amdgpu_gpu_instance
{
	struct amdgpu_device		*adev;
	int				mgpu_fan_enabled;
};

struct amdgpu_mgpu_info
{
	struct amdgpu_gpu_instance	gpu_ins[MAX_GPU_INSTANCE];
	struct mutex			mutex;
	uint32_t			num_gpu;
	uint32_t			num_dgpu;
	uint32_t			num_apu;
};

/*
 * Modules parameters.
 */
@@ -134,6 +151,7 @@ extern int amdgpu_compute_multipipe;
extern int amdgpu_gpu_recovery;
extern int amdgpu_emu_mode;
extern uint amdgpu_smu_memory_pool_size;
extern struct amdgpu_mgpu_info mgpu_info;

#ifdef CONFIG_DRM_AMDGPU_SI
extern int amdgpu_si_support;
@@ -598,31 +616,6 @@ void amdgpu_benchmark(struct amdgpu_device *adev, int test_number);
 */
void amdgpu_test_moves(struct amdgpu_device *adev);


/*
 * amdgpu smumgr functions
 */
struct amdgpu_smumgr_funcs {
	int (*check_fw_load_finish)(struct amdgpu_device *adev, uint32_t fwtype);
	int (*request_smu_load_fw)(struct amdgpu_device *adev);
	int (*request_smu_specific_fw)(struct amdgpu_device *adev, uint32_t fwtype);
};

/*
 * amdgpu smumgr
 */
struct amdgpu_smumgr {
	struct amdgpu_bo *toc_buf;
	struct amdgpu_bo *smu_buf;
	/* asic priv smu data */
	void *priv;
	spinlock_t smu_lock;
	/* smumgr functions */
	const struct amdgpu_smumgr_funcs *smumgr_funcs;
	/* ucode loading complete flag */
	uint32_t fw_flags;
};

/*
 * ASIC specific register table accessible by UMD
 */
@@ -958,9 +951,6 @@ struct amdgpu_device {
	u32				cg_flags;
	u32				pg_flags;

	/* amdgpu smumgr */
	struct amdgpu_smumgr smu;

	/* gfx */
	struct amdgpu_gfx		gfx;

@@ -1025,6 +1015,9 @@ struct amdgpu_device {
	bool has_hw_reset;
	u8				reset_magic[AMDGPU_RESET_MAGIC_NUM];

	/* s3/s4 mask */
	bool                            in_suspend;

	/* record last mm index being written through WREG32*/
	unsigned long last_mm_index;
	bool                            in_gpu_reset;
+12 −5
Original line number Diff line number Diff line
@@ -359,7 +359,9 @@ static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif,
 *
 * Checks the acpi event and if it matches an atif event,
 * handles it.
 * Returns NOTIFY code
 *
 * Returns:
 * NOTIFY_BAD or NOTIFY_DONE, depending on the event.
 */
static int amdgpu_atif_handler(struct amdgpu_device *adev,
			       struct acpi_bus_event *event)
@@ -373,11 +375,16 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
	if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
		return NOTIFY_DONE;

	/* Is this actually our event? */
	if (!atif ||
	    !atif->notification_cfg.enabled ||
	    event->type != atif->notification_cfg.command_code)
		/* Not our event */
	    event->type != atif->notification_cfg.command_code) {
		/* These events will generate keypresses otherwise */
		if (event->type == ACPI_VIDEO_NOTIFY_PROBE)
			return NOTIFY_BAD;
		else
			return NOTIFY_DONE;
	}

	if (atif->functions.sbios_requests) {
		struct atif_sbios_requests req;
@@ -386,7 +393,7 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
		count = amdgpu_atif_get_sbios_requests(atif, &req);

		if (count <= 0)
			return NOTIFY_DONE;
			return NOTIFY_BAD;

		DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count);

+165 −18
Original line number Diff line number Diff line
@@ -1525,6 +1525,92 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
	return 0;
}

static int amdgpu_device_ip_hw_init_phase1(struct amdgpu_device *adev)
{
	int i, r;

	for (i = 0; i < adev->num_ip_blocks; i++) {
		if (!adev->ip_blocks[i].status.sw)
			continue;
		if (adev->ip_blocks[i].status.hw)
			continue;
		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
			r = adev->ip_blocks[i].version->funcs->hw_init(adev);
			if (r) {
				DRM_ERROR("hw_init of IP block <%s> failed %d\n",
					  adev->ip_blocks[i].version->funcs->name, r);
				return r;
			}
			adev->ip_blocks[i].status.hw = true;
		}
	}

	return 0;
}

static int amdgpu_device_ip_hw_init_phase2(struct amdgpu_device *adev)
{
	int i, r;

	for (i = 0; i < adev->num_ip_blocks; i++) {
		if (!adev->ip_blocks[i].status.sw)
			continue;
		if (adev->ip_blocks[i].status.hw)
			continue;
		r = adev->ip_blocks[i].version->funcs->hw_init(adev);
		if (r) {
			DRM_ERROR("hw_init of IP block <%s> failed %d\n",
				  adev->ip_blocks[i].version->funcs->name, r);
			return r;
		}
		adev->ip_blocks[i].status.hw = true;
	}

	return 0;
}

static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
{
	int r = 0;
	int i;

	if (adev->asic_type >= CHIP_VEGA10) {
		for (i = 0; i < adev->num_ip_blocks; i++) {
			if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
				if (adev->in_gpu_reset || adev->in_suspend) {
					if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset)
						break; /* sriov gpu reset, psp need to do hw_init before IH because of hw limit */
					r = adev->ip_blocks[i].version->funcs->resume(adev);
					if (r) {
						DRM_ERROR("resume of IP block <%s> failed %d\n",
							  adev->ip_blocks[i].version->funcs->name, r);
						return r;
					}
				} else {
					r = adev->ip_blocks[i].version->funcs->hw_init(adev);
					if (r) {
						DRM_ERROR("hw_init of IP block <%s> failed %d\n",
						  adev->ip_blocks[i].version->funcs->name, r);
						return r;
					}
				}
				adev->ip_blocks[i].status.hw = true;
			}
		}
	}

	if (adev->powerplay.pp_funcs->load_firmware) {
		r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle);
		if (r) {
			pr_err("firmware loading failed\n");
			return r;
		}
	}

	return 0;
}

/**
 * amdgpu_device_ip_init - run init for hardware IPs
 *
@@ -1581,19 +1667,21 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
		}
	}

	for (i = 0; i < adev->num_ip_blocks; i++) {
		if (!adev->ip_blocks[i].status.sw)
			continue;
		if (adev->ip_blocks[i].status.hw)
			continue;
		r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
		if (r) {
			DRM_ERROR("hw_init of IP block <%s> failed %d\n",
				  adev->ip_blocks[i].version->funcs->name, r);
	r = amdgpu_ucode_create_bo(adev); /* create ucode bo when sw_init complete*/
	if (r)
		return r;

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

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

	r = amdgpu_device_ip_hw_init_phase2(adev);
	if (r)
		return r;
		}
		adev->ip_blocks[i].status.hw = true;
	}

	amdgpu_xgmi_add_device(adev);
	amdgpu_amdkfd_device_init(adev);
@@ -1656,7 +1744,7 @@ static int amdgpu_device_set_cg_state(struct amdgpu_device *adev,

	for (j = 0; j < adev->num_ip_blocks; j++) {
		i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
		if (!adev->ip_blocks[i].status.valid)
		if (!adev->ip_blocks[i].status.late_initialized)
			continue;
		/* skip CG for VCE/UVD, it's handled specially */
		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
@@ -1686,7 +1774,7 @@ static int amdgpu_device_set_pg_state(struct amdgpu_device *adev, enum amd_power

	for (j = 0; j < adev->num_ip_blocks; j++) {
		i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
		if (!adev->ip_blocks[i].status.valid)
		if (!adev->ip_blocks[i].status.late_initialized)
			continue;
		/* skip CG for VCE/UVD, it's handled specially */
		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
@@ -1723,7 +1811,7 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
	int i = 0, r;

	for (i = 0; i < adev->num_ip_blocks; i++) {
		if (!adev->ip_blocks[i].status.valid)
		if (!adev->ip_blocks[i].status.hw)
			continue;
		if (adev->ip_blocks[i].version->funcs->late_init) {
			r = adev->ip_blocks[i].version->funcs->late_init((void *)adev);
@@ -1732,8 +1820,8 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
					  adev->ip_blocks[i].version->funcs->name, r);
				return r;
			}
			adev->ip_blocks[i].status.late_initialized = true;
		}
		adev->ip_blocks[i].status.late_initialized = true;
	}

	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
@@ -1803,6 +1891,7 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
			continue;

		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
			amdgpu_ucode_free_bo(adev);
			amdgpu_free_static_csa(adev);
			amdgpu_device_wb_fini(adev);
			amdgpu_device_vram_scratch_fini(adev);
@@ -1833,6 +1922,43 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
	return 0;
}

static int amdgpu_device_enable_mgpu_fan_boost(void)
{
	struct amdgpu_gpu_instance *gpu_ins;
	struct amdgpu_device *adev;
	int i, ret = 0;

	mutex_lock(&mgpu_info.mutex);

	/*
	 * MGPU fan boost feature should be enabled
	 * only when there are two or more dGPUs in
	 * the system
	 */
	if (mgpu_info.num_dgpu < 2)
		goto out;

	for (i = 0; i < mgpu_info.num_dgpu; i++) {
		gpu_ins = &(mgpu_info.gpu_ins[i]);
		adev = gpu_ins->adev;
		if (!(adev->flags & AMD_IS_APU) &&
		    !gpu_ins->mgpu_fan_enabled &&
		    adev->powerplay.pp_funcs &&
		    adev->powerplay.pp_funcs->enable_mgpu_fan_boost) {
			ret = amdgpu_dpm_enable_mgpu_fan_boost(adev);
			if (ret)
				break;

			gpu_ins->mgpu_fan_enabled = 1;
		}
	}

out:
	mutex_unlock(&mgpu_info.mutex);

	return ret;
}

/**
 * amdgpu_device_ip_late_init_func_handler - work handler for ib test
 *
@@ -1847,6 +1973,10 @@ static void amdgpu_device_ip_late_init_func_handler(struct work_struct *work)
	r = amdgpu_ib_ring_tests(adev);
	if (r)
		DRM_ERROR("ib ring test failed (%d).\n", r);

	r = amdgpu_device_enable_mgpu_fan_boost();
	if (r)
		DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
}

static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)
@@ -2082,7 +2212,8 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
			continue;
		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH)
		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
		    adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
			continue;
		r = adev->ip_blocks[i].version->funcs->resume(adev);
		if (r) {
@@ -2114,6 +2245,11 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
	r = amdgpu_device_ip_resume_phase1(adev);
	if (r)
		return r;

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

	r = amdgpu_device_ip_resume_phase2(adev);

	return r;
@@ -2608,6 +2744,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		return 0;

	adev->in_suspend = true;
	drm_kms_helper_poll_disable(dev);

	if (fbcon)
@@ -2793,6 +2930,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
#ifdef CONFIG_PM
	dev->dev->power.disable_depth--;
#endif
	adev->in_suspend = false;

	return 0;
}

@@ -3061,6 +3200,10 @@ static int amdgpu_device_reset(struct amdgpu_device *adev)
			if (r)
				goto out;

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

			r = amdgpu_device_ip_resume_phase2(adev);
			if (r)
				goto out;
@@ -3117,6 +3260,10 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
	/* we need recover gart prior to run SMC/CP/SDMA resume */
	amdgpu_gtt_mgr_recover(&adev->mman.bdev.man[TTM_PL_TT]);

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

	/* now we are okay to resume SMC/CP/SDMA */
	r = amdgpu_device_ip_reinit_late_sriov(adev);
	if (r)
+7 −0
Original line number Diff line number Diff line
@@ -278,6 +278,9 @@ enum amdgpu_pcie_gen {
#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \
		((adev)->powerplay.pp_funcs->get_fan_speed_rpm)((adev)->powerplay.pp_handle, (s))

#define amdgpu_dpm_set_fan_speed_rpm(adev, s) \
		((adev)->powerplay.pp_funcs->set_fan_speed_rpm)((adev)->powerplay.pp_handle, (s))

#define amdgpu_dpm_get_sclk(adev, l) \
		((adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)))

@@ -357,6 +360,10 @@ enum amdgpu_pcie_gen {
		((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\
			(adev)->powerplay.pp_handle, type, parameter, size))

#define amdgpu_dpm_enable_mgpu_fan_boost(adev) \
		((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\
			(adev)->powerplay.pp_handle))

struct amdgpu_dpm {
	struct amdgpu_ps        *ps;
	/* number of valid power states */
+3 −0
Original line number Diff line number Diff line
@@ -127,6 +127,9 @@ int amdgpu_compute_multipipe = -1;
int amdgpu_gpu_recovery = -1; /* auto */
int amdgpu_emu_mode = 0;
uint amdgpu_smu_memory_pool_size = 0;
struct amdgpu_mgpu_info mgpu_info = {
	.mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
};

/**
 * DOC: vramlimit (int)
Loading