mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
drm/radeon: split ATRM support out from the ATPX handler (v3)
There are systems that use ATRM, but not ATPX. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=41265 V2: fix #ifdefs as per Greg's comments V3: fix it harder Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
7c3906d04a
commit
c61e277587
3 changed files with 77 additions and 74 deletions
|
@ -142,21 +142,6 @@ struct radeon_device;
|
|||
/*
|
||||
* BIOS.
|
||||
*/
|
||||
#define ATRM_BIOS_PAGE 4096
|
||||
|
||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||
bool radeon_atrm_supported(struct pci_dev *pdev);
|
||||
int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len);
|
||||
#else
|
||||
static inline bool radeon_atrm_supported(struct pci_dev *pdev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
bool radeon_get_bios(struct radeon_device *rdev);
|
||||
|
||||
/*
|
||||
|
|
|
@ -30,57 +30,8 @@ static struct radeon_atpx_priv {
|
|||
/* handle for device - and atpx */
|
||||
acpi_handle dhandle;
|
||||
acpi_handle atpx_handle;
|
||||
acpi_handle atrm_handle;
|
||||
} radeon_atpx_priv;
|
||||
|
||||
/* retrieve the ROM in 4k blocks */
|
||||
static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
|
||||
int offset, int len)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_object atrm_arg_elements[2], *obj;
|
||||
struct acpi_object_list atrm_arg;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
|
||||
|
||||
atrm_arg.count = 2;
|
||||
atrm_arg.pointer = &atrm_arg_elements[0];
|
||||
|
||||
atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
|
||||
atrm_arg_elements[0].integer.value = offset;
|
||||
|
||||
atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
|
||||
atrm_arg_elements[1].integer.value = len;
|
||||
|
||||
status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
obj = (union acpi_object *)buffer.pointer;
|
||||
memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
|
||||
len = obj->buffer.length;
|
||||
kfree(buffer.pointer);
|
||||
return len;
|
||||
}
|
||||
|
||||
bool radeon_atrm_supported(struct pci_dev *pdev)
|
||||
{
|
||||
/* get the discrete ROM only via ATRM */
|
||||
if (!radeon_atpx_priv.atpx_detected)
|
||||
return false;
|
||||
|
||||
if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len)
|
||||
{
|
||||
return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len);
|
||||
}
|
||||
|
||||
static int radeon_atpx_get_version(acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
|
@ -198,7 +149,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
|
|||
|
||||
static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
|
||||
{
|
||||
acpi_handle dhandle, atpx_handle, atrm_handle;
|
||||
acpi_handle dhandle, atpx_handle;
|
||||
acpi_status status;
|
||||
|
||||
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
|
||||
|
@ -209,13 +160,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
|
|||
if (ACPI_FAILURE(status))
|
||||
return false;
|
||||
|
||||
status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
return false;
|
||||
|
||||
radeon_atpx_priv.dhandle = dhandle;
|
||||
radeon_atpx_priv.atpx_handle = atpx_handle;
|
||||
radeon_atpx_priv.atrm_handle = atrm_handle;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,16 +99,81 @@ static bool radeon_read_bios(struct radeon_device *rdev)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
/* ATRM is used to get the BIOS on the discrete cards in
|
||||
* dual-gpu systems.
|
||||
*/
|
||||
/* retrieve the ROM in 4k blocks */
|
||||
#define ATRM_BIOS_PAGE 4096
|
||||
/**
|
||||
* radeon_atrm_call - fetch a chunk of the vbios
|
||||
*
|
||||
* @atrm_handle: acpi ATRM handle
|
||||
* @bios: vbios image pointer
|
||||
* @offset: offset of vbios image data to fetch
|
||||
* @len: length of vbios image data to fetch
|
||||
*
|
||||
* Executes ATRM to fetch a chunk of the discrete
|
||||
* vbios image on PX systems (all asics).
|
||||
* Returns the length of the buffer fetched.
|
||||
*/
|
||||
static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
|
||||
int offset, int len)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_object atrm_arg_elements[2], *obj;
|
||||
struct acpi_object_list atrm_arg;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
|
||||
|
||||
atrm_arg.count = 2;
|
||||
atrm_arg.pointer = &atrm_arg_elements[0];
|
||||
|
||||
atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
|
||||
atrm_arg_elements[0].integer.value = offset;
|
||||
|
||||
atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
|
||||
atrm_arg_elements[1].integer.value = len;
|
||||
|
||||
status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
obj = (union acpi_object *)buffer.pointer;
|
||||
memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
|
||||
len = obj->buffer.length;
|
||||
kfree(buffer.pointer);
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool radeon_atrm_get_bios(struct radeon_device *rdev)
|
||||
{
|
||||
int ret;
|
||||
int size = 256 * 1024;
|
||||
int i;
|
||||
struct pci_dev *pdev = NULL;
|
||||
acpi_handle dhandle, atrm_handle;
|
||||
acpi_status status;
|
||||
bool found = false;
|
||||
|
||||
if (!radeon_atrm_supported(rdev->pdev))
|
||||
/* ATRM is for the discrete card only */
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
return false;
|
||||
|
||||
while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
|
||||
dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
|
||||
if (!dhandle)
|
||||
continue;
|
||||
|
||||
status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
|
||||
if (!ACPI_FAILURE(status)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
rdev->bios = kmalloc(size, GFP_KERNEL);
|
||||
|
@ -118,9 +183,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
|
|||
}
|
||||
|
||||
for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
|
||||
ret = radeon_atrm_get_bios_chunk(rdev->bios,
|
||||
(i * ATRM_BIOS_PAGE),
|
||||
ATRM_BIOS_PAGE);
|
||||
ret = radeon_atrm_call(atrm_handle,
|
||||
rdev->bios,
|
||||
(i * ATRM_BIOS_PAGE),
|
||||
ATRM_BIOS_PAGE);
|
||||
if (ret < ATRM_BIOS_PAGE)
|
||||
break;
|
||||
}
|
||||
|
@ -131,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ni_read_disabled_bios(struct radeon_device *rdev)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue