diff mbox

[1/3] drm/radeon: add support for newer mc ucode on SI

Message ID 1397227931-2151-1-git-send-email-alexander.deucher@amd.com (mailing list archive)
State New, archived
Headers show

Commit Message

Alex Deucher April 11, 2014, 2:52 p.m. UTC
May fix stability issues with some newer cards.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
---
 drivers/gpu/drm/radeon/radeon_ucode.h |  3 +++
 drivers/gpu/drm/radeon/si.c           | 34 +++++++++++++++++++++-------------
 2 files changed, 24 insertions(+), 13 deletions(-)

Comments

Christian König April 11, 2014, 3:03 p.m. UTC | #1
Am 11.04.2014 16:52, schrieb Alex Deucher:
> May fix stability issues with some newer cards.
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> Cc: stable@vger.kernel.org

Why adding *_mc2.bin for the MC firmware? To distinct if people have the 
new or the old firmware?

If that's the case I would rather print the firmware size or CRC code 
somewhere in the logs.

Christian.

> ---
>   drivers/gpu/drm/radeon/radeon_ucode.h |  3 +++
>   drivers/gpu/drm/radeon/si.c           | 34 +++++++++++++++++++++-------------
>   2 files changed, 24 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h
> index a77cd27..f415548 100644
> --- a/drivers/gpu/drm/radeon/radeon_ucode.h
> +++ b/drivers/gpu/drm/radeon/radeon_ucode.h
> @@ -57,6 +57,9 @@
>   #define BTC_MC_UCODE_SIZE            6024
>   #define CAYMAN_MC_UCODE_SIZE         6037
>   #define SI_MC_UCODE_SIZE             7769
> +#define TAHITI_MC_UCODE_SIZE         7808
> +#define PITCAIRN_MC_UCODE_SIZE       7775
> +#define VERDE_MC_UCODE_SIZE          7875
>   #define OLAND_MC_UCODE_SIZE          7863
>   #define CIK_MC_UCODE_SIZE            7866
>   #define HAWAII_MC_UCODE_SIZE         7933
> diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
> index d589475..7675247 100644
> --- a/drivers/gpu/drm/radeon/si.c
> +++ b/drivers/gpu/drm/radeon/si.c
> @@ -39,30 +39,35 @@ MODULE_FIRMWARE("radeon/TAHITI_pfp.bin");
>   MODULE_FIRMWARE("radeon/TAHITI_me.bin");
>   MODULE_FIRMWARE("radeon/TAHITI_ce.bin");
>   MODULE_FIRMWARE("radeon/TAHITI_mc.bin");
> +MODULE_FIRMWARE("radeon/TAHITI_mc2.bin");
>   MODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
>   MODULE_FIRMWARE("radeon/TAHITI_smc.bin");
>   MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
>   MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
>   MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
>   MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
> +MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin");
>   MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
>   MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin");
>   MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
>   MODULE_FIRMWARE("radeon/VERDE_me.bin");
>   MODULE_FIRMWARE("radeon/VERDE_ce.bin");
>   MODULE_FIRMWARE("radeon/VERDE_mc.bin");
> +MODULE_FIRMWARE("radeon/VERDE_mc2.bin");
>   MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
>   MODULE_FIRMWARE("radeon/VERDE_smc.bin");
>   MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
>   MODULE_FIRMWARE("radeon/OLAND_me.bin");
>   MODULE_FIRMWARE("radeon/OLAND_ce.bin");
>   MODULE_FIRMWARE("radeon/OLAND_mc.bin");
> +MODULE_FIRMWARE("radeon/OLAND_mc2.bin");
>   MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
>   MODULE_FIRMWARE("radeon/OLAND_smc.bin");
>   MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
>   MODULE_FIRMWARE("radeon/HAINAN_me.bin");
>   MODULE_FIRMWARE("radeon/HAINAN_ce.bin");
>   MODULE_FIRMWARE("radeon/HAINAN_mc.bin");
> +MODULE_FIRMWARE("radeon/HAINAN_mc2.bin");
>   MODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
>   MODULE_FIRMWARE("radeon/HAINAN_smc.bin");
>   
> @@ -1467,7 +1472,7 @@ int si_mc_load_microcode(struct radeon_device *rdev)
>   	const __be32 *fw_data;
>   	u32 running, blackout = 0;
>   	u32 *io_mc_regs;
> -	int i, ucode_size, regs_size;
> +	int i, regs_size, ucode_size = rdev->mc_fw->size / 4;
>   
>   	if (!rdev->mc_fw)
>   		return -EINVAL;
> @@ -1475,28 +1480,23 @@ int si_mc_load_microcode(struct radeon_device *rdev)
>   	switch (rdev->family) {
>   	case CHIP_TAHITI:
>   		io_mc_regs = (u32 *)&tahiti_io_mc_regs;
> -		ucode_size = SI_MC_UCODE_SIZE;
>   		regs_size = TAHITI_IO_MC_REGS_SIZE;
>   		break;
>   	case CHIP_PITCAIRN:
>   		io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
> -		ucode_size = SI_MC_UCODE_SIZE;
>   		regs_size = TAHITI_IO_MC_REGS_SIZE;
>   		break;
>   	case CHIP_VERDE:
>   	default:
>   		io_mc_regs = (u32 *)&verde_io_mc_regs;
> -		ucode_size = SI_MC_UCODE_SIZE;
>   		regs_size = TAHITI_IO_MC_REGS_SIZE;
>   		break;
>   	case CHIP_OLAND:
>   		io_mc_regs = (u32 *)&oland_io_mc_regs;
> -		ucode_size = OLAND_MC_UCODE_SIZE;
>   		regs_size = TAHITI_IO_MC_REGS_SIZE;
>   		break;
>   	case CHIP_HAINAN:
>   		io_mc_regs = (u32 *)&hainan_io_mc_regs;
> -		ucode_size = OLAND_MC_UCODE_SIZE;
>   		regs_size = TAHITI_IO_MC_REGS_SIZE;
>   		break;
>   	}
> @@ -1552,7 +1552,7 @@ static int si_init_microcode(struct radeon_device *rdev)
>   	const char *chip_name;
>   	const char *rlc_chip_name;
>   	size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size;
> -	size_t smc_req_size;
> +	size_t smc_req_size, mc2_req_size;
>   	char fw_name[30];
>   	int err;
>   
> @@ -1567,6 +1567,7 @@ static int si_init_microcode(struct radeon_device *rdev)
>   		ce_req_size = SI_CE_UCODE_SIZE * 4;
>   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
>   		mc_req_size = SI_MC_UCODE_SIZE * 4;
> +		mc2_req_size = TAHITI_MC_UCODE_SIZE * 4;
>   		smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4);
>   		break;
>   	case CHIP_PITCAIRN:
> @@ -1577,6 +1578,7 @@ static int si_init_microcode(struct radeon_device *rdev)
>   		ce_req_size = SI_CE_UCODE_SIZE * 4;
>   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
>   		mc_req_size = SI_MC_UCODE_SIZE * 4;
> +		mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4;
>   		smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4);
>   		break;
>   	case CHIP_VERDE:
> @@ -1587,6 +1589,7 @@ static int si_init_microcode(struct radeon_device *rdev)
>   		ce_req_size = SI_CE_UCODE_SIZE * 4;
>   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
>   		mc_req_size = SI_MC_UCODE_SIZE * 4;
> +		mc2_req_size = VERDE_MC_UCODE_SIZE * 4;
>   		smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4);
>   		break;
>   	case CHIP_OLAND:
> @@ -1596,7 +1599,7 @@ static int si_init_microcode(struct radeon_device *rdev)
>   		me_req_size = SI_PM4_UCODE_SIZE * 4;
>   		ce_req_size = SI_CE_UCODE_SIZE * 4;
>   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
> -		mc_req_size = OLAND_MC_UCODE_SIZE * 4;
> +		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
>   		smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4);
>   		break;
>   	case CHIP_HAINAN:
> @@ -1606,7 +1609,7 @@ static int si_init_microcode(struct radeon_device *rdev)
>   		me_req_size = SI_PM4_UCODE_SIZE * 4;
>   		ce_req_size = SI_CE_UCODE_SIZE * 4;
>   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
> -		mc_req_size = OLAND_MC_UCODE_SIZE * 4;
> +		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
>   		smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4);
>   		break;
>   	default: BUG();
> @@ -1659,11 +1662,16 @@ static int si_init_microcode(struct radeon_device *rdev)
>   		err = -EINVAL;
>   	}
>   
> -	snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
> +	snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
>   	err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
> -	if (err)
> -		goto out;
> -	if (rdev->mc_fw->size != mc_req_size) {
> +	if (err) {
> +		snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
> +		err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
> +		if (err)
> +			goto out;
> +	}
> +	if ((rdev->mc_fw->size != mc_req_size) &&
> +	    (rdev->mc_fw->size != mc2_req_size)) {
>   		printk(KERN_ERR
>   		       "si_mc: Bogus length %zu in firmware \"%s\"\n",
>   		       rdev->mc_fw->size, fw_name);
Deucher, Alexander April 11, 2014, 3:05 p.m. UTC | #2
> -----Original Message-----
> From: Christian König [mailto:deathsimple@vodafone.de]
> Sent: Friday, April 11, 2014 11:03 AM
> To: Alex Deucher; dri-devel@lists.freedesktop.org
> Cc: Deucher, Alexander; stable@vger.kernel.org
> Subject: Re: [PATCH 1/3] drm/radeon: add support for newer mc ucode on SI
> 
> Am 11.04.2014 16:52, schrieb Alex Deucher:
> > May fix stability issues with some newer cards.
> >
> > Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> > Cc: stable@vger.kernel.org
> 
> Why adding *_mc2.bin for the MC firmware? To distinct if people have the
> new or the old firmware?

To make sure I don't  break old kernels mixed with new firmware.  E.g., is a user updated their ucode, but not their kernel, it would fail due to the firmware being the wrong size.

> 
> If that's the case I would rather print the firmware size or CRC code
> somewhere in the logs.

I'll add that and respin.

Alex

> 
> Christian.
> 
> > ---
> >   drivers/gpu/drm/radeon/radeon_ucode.h |  3 +++
> >   drivers/gpu/drm/radeon/si.c           | 34 +++++++++++++++++++++---------
> ----
> >   2 files changed, 24 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h
> b/drivers/gpu/drm/radeon/radeon_ucode.h
> > index a77cd27..f415548 100644
> > --- a/drivers/gpu/drm/radeon/radeon_ucode.h
> > +++ b/drivers/gpu/drm/radeon/radeon_ucode.h
> > @@ -57,6 +57,9 @@
> >   #define BTC_MC_UCODE_SIZE            6024
> >   #define CAYMAN_MC_UCODE_SIZE         6037
> >   #define SI_MC_UCODE_SIZE             7769
> > +#define TAHITI_MC_UCODE_SIZE         7808
> > +#define PITCAIRN_MC_UCODE_SIZE       7775
> > +#define VERDE_MC_UCODE_SIZE          7875
> >   #define OLAND_MC_UCODE_SIZE          7863
> >   #define CIK_MC_UCODE_SIZE            7866
> >   #define HAWAII_MC_UCODE_SIZE         7933
> > diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
> > index d589475..7675247 100644
> > --- a/drivers/gpu/drm/radeon/si.c
> > +++ b/drivers/gpu/drm/radeon/si.c
> > @@ -39,30 +39,35 @@ MODULE_FIRMWARE("radeon/TAHITI_pfp.bin");
> >   MODULE_FIRMWARE("radeon/TAHITI_me.bin");
> >   MODULE_FIRMWARE("radeon/TAHITI_ce.bin");
> >   MODULE_FIRMWARE("radeon/TAHITI_mc.bin");
> > +MODULE_FIRMWARE("radeon/TAHITI_mc2.bin");
> >   MODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
> >   MODULE_FIRMWARE("radeon/TAHITI_smc.bin");
> >   MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
> >   MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
> >   MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
> >   MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
> > +MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin");
> >   MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
> >   MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin");
> >   MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
> >   MODULE_FIRMWARE("radeon/VERDE_me.bin");
> >   MODULE_FIRMWARE("radeon/VERDE_ce.bin");
> >   MODULE_FIRMWARE("radeon/VERDE_mc.bin");
> > +MODULE_FIRMWARE("radeon/VERDE_mc2.bin");
> >   MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
> >   MODULE_FIRMWARE("radeon/VERDE_smc.bin");
> >   MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
> >   MODULE_FIRMWARE("radeon/OLAND_me.bin");
> >   MODULE_FIRMWARE("radeon/OLAND_ce.bin");
> >   MODULE_FIRMWARE("radeon/OLAND_mc.bin");
> > +MODULE_FIRMWARE("radeon/OLAND_mc2.bin");
> >   MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
> >   MODULE_FIRMWARE("radeon/OLAND_smc.bin");
> >   MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
> >   MODULE_FIRMWARE("radeon/HAINAN_me.bin");
> >   MODULE_FIRMWARE("radeon/HAINAN_ce.bin");
> >   MODULE_FIRMWARE("radeon/HAINAN_mc.bin");
> > +MODULE_FIRMWARE("radeon/HAINAN_mc2.bin");
> >   MODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
> >   MODULE_FIRMWARE("radeon/HAINAN_smc.bin");
> >
> > @@ -1467,7 +1472,7 @@ int si_mc_load_microcode(struct radeon_device
> *rdev)
> >   	const __be32 *fw_data;
> >   	u32 running, blackout = 0;
> >   	u32 *io_mc_regs;
> > -	int i, ucode_size, regs_size;
> > +	int i, regs_size, ucode_size = rdev->mc_fw->size / 4;
> >
> >   	if (!rdev->mc_fw)
> >   		return -EINVAL;
> > @@ -1475,28 +1480,23 @@ int si_mc_load_microcode(struct
> radeon_device *rdev)
> >   	switch (rdev->family) {
> >   	case CHIP_TAHITI:
> >   		io_mc_regs = (u32 *)&tahiti_io_mc_regs;
> > -		ucode_size = SI_MC_UCODE_SIZE;
> >   		regs_size = TAHITI_IO_MC_REGS_SIZE;
> >   		break;
> >   	case CHIP_PITCAIRN:
> >   		io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
> > -		ucode_size = SI_MC_UCODE_SIZE;
> >   		regs_size = TAHITI_IO_MC_REGS_SIZE;
> >   		break;
> >   	case CHIP_VERDE:
> >   	default:
> >   		io_mc_regs = (u32 *)&verde_io_mc_regs;
> > -		ucode_size = SI_MC_UCODE_SIZE;
> >   		regs_size = TAHITI_IO_MC_REGS_SIZE;
> >   		break;
> >   	case CHIP_OLAND:
> >   		io_mc_regs = (u32 *)&oland_io_mc_regs;
> > -		ucode_size = OLAND_MC_UCODE_SIZE;
> >   		regs_size = TAHITI_IO_MC_REGS_SIZE;
> >   		break;
> >   	case CHIP_HAINAN:
> >   		io_mc_regs = (u32 *)&hainan_io_mc_regs;
> > -		ucode_size = OLAND_MC_UCODE_SIZE;
> >   		regs_size = TAHITI_IO_MC_REGS_SIZE;
> >   		break;
> >   	}
> > @@ -1552,7 +1552,7 @@ static int si_init_microcode(struct radeon_device
> *rdev)
> >   	const char *chip_name;
> >   	const char *rlc_chip_name;
> >   	size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size,
> mc_req_size;
> > -	size_t smc_req_size;
> > +	size_t smc_req_size, mc2_req_size;
> >   	char fw_name[30];
> >   	int err;
> >
> > @@ -1567,6 +1567,7 @@ static int si_init_microcode(struct radeon_device
> *rdev)
> >   		ce_req_size = SI_CE_UCODE_SIZE * 4;
> >   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
> >   		mc_req_size = SI_MC_UCODE_SIZE * 4;
> > +		mc2_req_size = TAHITI_MC_UCODE_SIZE * 4;
> >   		smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4);
> >   		break;
> >   	case CHIP_PITCAIRN:
> > @@ -1577,6 +1578,7 @@ static int si_init_microcode(struct radeon_device
> *rdev)
> >   		ce_req_size = SI_CE_UCODE_SIZE * 4;
> >   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
> >   		mc_req_size = SI_MC_UCODE_SIZE * 4;
> > +		mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4;
> >   		smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4);
> >   		break;
> >   	case CHIP_VERDE:
> > @@ -1587,6 +1589,7 @@ static int si_init_microcode(struct radeon_device
> *rdev)
> >   		ce_req_size = SI_CE_UCODE_SIZE * 4;
> >   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
> >   		mc_req_size = SI_MC_UCODE_SIZE * 4;
> > +		mc2_req_size = VERDE_MC_UCODE_SIZE * 4;
> >   		smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4);
> >   		break;
> >   	case CHIP_OLAND:
> > @@ -1596,7 +1599,7 @@ static int si_init_microcode(struct radeon_device
> *rdev)
> >   		me_req_size = SI_PM4_UCODE_SIZE * 4;
> >   		ce_req_size = SI_CE_UCODE_SIZE * 4;
> >   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
> > -		mc_req_size = OLAND_MC_UCODE_SIZE * 4;
> > +		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
> >   		smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4);
> >   		break;
> >   	case CHIP_HAINAN:
> > @@ -1606,7 +1609,7 @@ static int si_init_microcode(struct radeon_device
> *rdev)
> >   		me_req_size = SI_PM4_UCODE_SIZE * 4;
> >   		ce_req_size = SI_CE_UCODE_SIZE * 4;
> >   		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
> > -		mc_req_size = OLAND_MC_UCODE_SIZE * 4;
> > +		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
> >   		smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4);
> >   		break;
> >   	default: BUG();
> > @@ -1659,11 +1662,16 @@ static int si_init_microcode(struct
> radeon_device *rdev)
> >   		err = -EINVAL;
> >   	}
> >
> > -	snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin",
> chip_name);
> > +	snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin",
> chip_name);
> >   	err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
> > -	if (err)
> > -		goto out;
> > -	if (rdev->mc_fw->size != mc_req_size) {
> > +	if (err) {
> > +		snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin",
> chip_name);
> > +		err = request_firmware(&rdev->mc_fw, fw_name, rdev-
> >dev);
> > +		if (err)
> > +			goto out;
> > +	}
> > +	if ((rdev->mc_fw->size != mc_req_size) &&
> > +	    (rdev->mc_fw->size != mc2_req_size)) {
> >   		printk(KERN_ERR
> >   		       "si_mc: Bogus length %zu in firmware \"%s\"\n",
> >   		       rdev->mc_fw->size, fw_name);
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h
index a77cd27..f415548 100644
--- a/drivers/gpu/drm/radeon/radeon_ucode.h
+++ b/drivers/gpu/drm/radeon/radeon_ucode.h
@@ -57,6 +57,9 @@ 
 #define BTC_MC_UCODE_SIZE            6024
 #define CAYMAN_MC_UCODE_SIZE         6037
 #define SI_MC_UCODE_SIZE             7769
+#define TAHITI_MC_UCODE_SIZE         7808
+#define PITCAIRN_MC_UCODE_SIZE       7775
+#define VERDE_MC_UCODE_SIZE          7875
 #define OLAND_MC_UCODE_SIZE          7863
 #define CIK_MC_UCODE_SIZE            7866
 #define HAWAII_MC_UCODE_SIZE         7933
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index d589475..7675247 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -39,30 +39,35 @@  MODULE_FIRMWARE("radeon/TAHITI_pfp.bin");
 MODULE_FIRMWARE("radeon/TAHITI_me.bin");
 MODULE_FIRMWARE("radeon/TAHITI_ce.bin");
 MODULE_FIRMWARE("radeon/TAHITI_mc.bin");
+MODULE_FIRMWARE("radeon/TAHITI_mc2.bin");
 MODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
 MODULE_FIRMWARE("radeon/TAHITI_smc.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
+MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
 MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin");
 MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
 MODULE_FIRMWARE("radeon/VERDE_me.bin");
 MODULE_FIRMWARE("radeon/VERDE_ce.bin");
 MODULE_FIRMWARE("radeon/VERDE_mc.bin");
+MODULE_FIRMWARE("radeon/VERDE_mc2.bin");
 MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
 MODULE_FIRMWARE("radeon/VERDE_smc.bin");
 MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
 MODULE_FIRMWARE("radeon/OLAND_me.bin");
 MODULE_FIRMWARE("radeon/OLAND_ce.bin");
 MODULE_FIRMWARE("radeon/OLAND_mc.bin");
+MODULE_FIRMWARE("radeon/OLAND_mc2.bin");
 MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
 MODULE_FIRMWARE("radeon/OLAND_smc.bin");
 MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
 MODULE_FIRMWARE("radeon/HAINAN_me.bin");
 MODULE_FIRMWARE("radeon/HAINAN_ce.bin");
 MODULE_FIRMWARE("radeon/HAINAN_mc.bin");
+MODULE_FIRMWARE("radeon/HAINAN_mc2.bin");
 MODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
 MODULE_FIRMWARE("radeon/HAINAN_smc.bin");
 
@@ -1467,7 +1472,7 @@  int si_mc_load_microcode(struct radeon_device *rdev)
 	const __be32 *fw_data;
 	u32 running, blackout = 0;
 	u32 *io_mc_regs;
-	int i, ucode_size, regs_size;
+	int i, regs_size, ucode_size = rdev->mc_fw->size / 4;
 
 	if (!rdev->mc_fw)
 		return -EINVAL;
@@ -1475,28 +1480,23 @@  int si_mc_load_microcode(struct radeon_device *rdev)
 	switch (rdev->family) {
 	case CHIP_TAHITI:
 		io_mc_regs = (u32 *)&tahiti_io_mc_regs;
-		ucode_size = SI_MC_UCODE_SIZE;
 		regs_size = TAHITI_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_PITCAIRN:
 		io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
-		ucode_size = SI_MC_UCODE_SIZE;
 		regs_size = TAHITI_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_VERDE:
 	default:
 		io_mc_regs = (u32 *)&verde_io_mc_regs;
-		ucode_size = SI_MC_UCODE_SIZE;
 		regs_size = TAHITI_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_OLAND:
 		io_mc_regs = (u32 *)&oland_io_mc_regs;
-		ucode_size = OLAND_MC_UCODE_SIZE;
 		regs_size = TAHITI_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_HAINAN:
 		io_mc_regs = (u32 *)&hainan_io_mc_regs;
-		ucode_size = OLAND_MC_UCODE_SIZE;
 		regs_size = TAHITI_IO_MC_REGS_SIZE;
 		break;
 	}
@@ -1552,7 +1552,7 @@  static int si_init_microcode(struct radeon_device *rdev)
 	const char *chip_name;
 	const char *rlc_chip_name;
 	size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size;
-	size_t smc_req_size;
+	size_t smc_req_size, mc2_req_size;
 	char fw_name[30];
 	int err;
 
@@ -1567,6 +1567,7 @@  static int si_init_microcode(struct radeon_device *rdev)
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
 		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
 		mc_req_size = SI_MC_UCODE_SIZE * 4;
+		mc2_req_size = TAHITI_MC_UCODE_SIZE * 4;
 		smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4);
 		break;
 	case CHIP_PITCAIRN:
@@ -1577,6 +1578,7 @@  static int si_init_microcode(struct radeon_device *rdev)
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
 		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
 		mc_req_size = SI_MC_UCODE_SIZE * 4;
+		mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4;
 		smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4);
 		break;
 	case CHIP_VERDE:
@@ -1587,6 +1589,7 @@  static int si_init_microcode(struct radeon_device *rdev)
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
 		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
 		mc_req_size = SI_MC_UCODE_SIZE * 4;
+		mc2_req_size = VERDE_MC_UCODE_SIZE * 4;
 		smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4);
 		break;
 	case CHIP_OLAND:
@@ -1596,7 +1599,7 @@  static int si_init_microcode(struct radeon_device *rdev)
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
 		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
-		mc_req_size = OLAND_MC_UCODE_SIZE * 4;
+		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
 		smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4);
 		break;
 	case CHIP_HAINAN:
@@ -1606,7 +1609,7 @@  static int si_init_microcode(struct radeon_device *rdev)
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
 		ce_req_size = SI_CE_UCODE_SIZE * 4;
 		rlc_req_size = SI_RLC_UCODE_SIZE * 4;
-		mc_req_size = OLAND_MC_UCODE_SIZE * 4;
+		mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
 		smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4);
 		break;
 	default: BUG();
@@ -1659,11 +1662,16 @@  static int si_init_microcode(struct radeon_device *rdev)
 		err = -EINVAL;
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+	snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
 	err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
-	if (err)
-		goto out;
-	if (rdev->mc_fw->size != mc_req_size) {
+	if (err) {
+		snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
+		err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
+		if (err)
+			goto out;
+	}
+	if ((rdev->mc_fw->size != mc_req_size) &&
+	    (rdev->mc_fw->size != mc2_req_size)) {
 		printk(KERN_ERR
 		       "si_mc: Bogus length %zu in firmware \"%s\"\n",
 		       rdev->mc_fw->size, fw_name);