aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0326-drm-amdgpu-clean-up-init-sequence-for-failures.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0326-drm-amdgpu-clean-up-init-sequence-for-failures.patch')
-rw-r--r--meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0326-drm-amdgpu-clean-up-init-sequence-for-failures.patch213
1 files changed, 213 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0326-drm-amdgpu-clean-up-init-sequence-for-failures.patch b/meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0326-drm-amdgpu-clean-up-init-sequence-for-failures.patch
new file mode 100644
index 00000000..63a14dfd
--- /dev/null
+++ b/meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0326-drm-amdgpu-clean-up-init-sequence-for-failures.patch
@@ -0,0 +1,213 @@
+From 8faf0e08d5a78ae5f1752b1d69f97ed70afa625f Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 28 Jul 2015 11:50:31 -0400
+Subject: [PATCH 0326/1050] drm/amdgpu: clean up init sequence for failures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If we fail during device init, record what state each
+block is in so that we can tear down clearly.
+
+Fixes various problems on device init failure.
+
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 ++++++-
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 38 +++++++++++++++++-------------
+ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++--
+ 3 files changed, 31 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+index e9fde72..31b00f9 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -1866,6 +1866,12 @@ typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
+ typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
+ typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
+
++struct amdgpu_ip_block_status {
++ bool valid;
++ bool sw;
++ bool hw;
++};
++
+ struct amdgpu_device {
+ struct device *dev;
+ struct drm_device *ddev;
+@@ -2008,7 +2014,7 @@ struct amdgpu_device {
+
+ const struct amdgpu_ip_block_version *ip_blocks;
+ int num_ip_blocks;
+- bool *ip_block_enabled;
++ struct amdgpu_ip_block_status *ip_block_status;
+ struct mutex mn_lock;
+ DECLARE_HASHTABLE(mn_hash, 7);
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index d79009b..99f158e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -1191,8 +1191,9 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
+ return -EINVAL;
+ }
+
+- adev->ip_block_enabled = kcalloc(adev->num_ip_blocks, sizeof(bool), GFP_KERNEL);
+- if (adev->ip_block_enabled == NULL)
++ adev->ip_block_status = kcalloc(adev->num_ip_blocks,
++ sizeof(struct amdgpu_ip_block_status), GFP_KERNEL);
++ if (adev->ip_block_status == NULL)
+ return -ENOMEM;
+
+ if (adev->ip_blocks == NULL) {
+@@ -1203,18 +1204,18 @@ static int amdgpu_early_init(struct amdgpu_device *adev)
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
+ DRM_ERROR("disabled ip block: %d\n", i);
+- adev->ip_block_enabled[i] = false;
++ adev->ip_block_status[i].valid = false;
+ } else {
+ if (adev->ip_blocks[i].funcs->early_init) {
+ r = adev->ip_blocks[i].funcs->early_init((void *)adev);
+ if (r == -ENOENT)
+- adev->ip_block_enabled[i] = false;
++ adev->ip_block_status[i].valid = false;
+ else if (r)
+ return r;
+ else
+- adev->ip_block_enabled[i] = true;
++ adev->ip_block_status[i].valid = true;
+ } else {
+- adev->ip_block_enabled[i] = true;
++ adev->ip_block_status[i].valid = true;
+ }
+ }
+ }
+@@ -1227,11 +1228,12 @@ static int amdgpu_init(struct amdgpu_device *adev)
+ int i, r;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+- if (!adev->ip_block_enabled[i])
++ if (!adev->ip_block_status[i].valid)
+ continue;
+ r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
+ if (r)
+ return r;
++ adev->ip_block_status[i].sw = true;
+ /* need to do gmc hw init early so we can allocate gpu mem */
+ if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
+ r = amdgpu_vram_scratch_init(adev);
+@@ -1243,11 +1245,12 @@ static int amdgpu_init(struct amdgpu_device *adev)
+ r = amdgpu_wb_init(adev);
+ if (r)
+ return r;
++ adev->ip_block_status[i].hw = true;
+ }
+ }
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+- if (!adev->ip_block_enabled[i])
++ if (!adev->ip_block_status[i].sw)
+ continue;
+ /* gmc hw init is done early */
+ if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC)
+@@ -1255,6 +1258,7 @@ static int amdgpu_init(struct amdgpu_device *adev)
+ r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
+ if (r)
+ return r;
++ adev->ip_block_status[i].hw = true;
+ }
+
+ return 0;
+@@ -1265,7 +1269,7 @@ static int amdgpu_late_init(struct amdgpu_device *adev)
+ int i = 0, r;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+- if (!adev->ip_block_enabled[i])
++ if (!adev->ip_block_status[i].valid)
+ continue;
+ /* enable clockgating to save power */
+ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
+@@ -1287,7 +1291,7 @@ static int amdgpu_fini(struct amdgpu_device *adev)
+ int i, r;
+
+ for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
+- if (!adev->ip_block_enabled[i])
++ if (!adev->ip_block_status[i].hw)
+ continue;
+ if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
+ amdgpu_wb_fini(adev);
+@@ -1300,14 +1304,16 @@ static int amdgpu_fini(struct amdgpu_device *adev)
+ return r;
+ r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
+ /* XXX handle errors */
++ adev->ip_block_status[i].hw = false;
+ }
+
+ for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
+- if (!adev->ip_block_enabled[i])
++ if (!adev->ip_block_status[i].sw)
+ continue;
+ r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
+ /* XXX handle errors */
+- adev->ip_block_enabled[i] = false;
++ adev->ip_block_status[i].sw = false;
++ adev->ip_block_status[i].valid = false;
+ }
+
+ return 0;
+@@ -1318,7 +1324,7 @@ static int amdgpu_suspend(struct amdgpu_device *adev)
+ int i, r;
+
+ for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
+- if (!adev->ip_block_enabled[i])
++ if (!adev->ip_block_status[i].valid)
+ continue;
+ /* ungate blocks so that suspend can properly shut them down */
+ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
+@@ -1336,7 +1342,7 @@ static int amdgpu_resume(struct amdgpu_device *adev)
+ int i, r;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+- if (!adev->ip_block_enabled[i])
++ if (!adev->ip_block_status[i].valid)
+ continue;
+ r = adev->ip_blocks[i].funcs->resume(adev);
+ if (r)
+@@ -1582,8 +1588,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
+ amdgpu_fence_driver_fini(adev);
+ amdgpu_fbdev_fini(adev);
+ r = amdgpu_fini(adev);
+- kfree(adev->ip_block_enabled);
+- adev->ip_block_enabled = NULL;
++ kfree(adev->ip_block_status);
++ adev->ip_block_status = NULL;
+ adev->accel_working = false;
+ /* free i2c buses */
+ amdgpu_i2c_fini(adev);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+index 31ad444..d316bda 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+@@ -235,7 +235,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (adev->ip_blocks[i].type == type &&
+- adev->ip_block_enabled[i]) {
++ adev->ip_block_status[i].valid) {
+ ip.hw_ip_version_major = adev->ip_blocks[i].major;
+ ip.hw_ip_version_minor = adev->ip_blocks[i].minor;
+ ip.capabilities_flags = 0;
+@@ -274,7 +274,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
+
+ for (i = 0; i < adev->num_ip_blocks; i++)
+ if (adev->ip_blocks[i].type == type &&
+- adev->ip_block_enabled[i] &&
++ adev->ip_block_status[i].valid &&
+ count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
+ count++;
+
+--
+1.9.1
+