* [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch
@ 2012-08-16 17:54 alexdeucher
2012-08-16 17:54 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler alexdeucher
` (2 more replies)
0 siblings, 3 replies; 23+ messages in thread
From: alexdeucher @ 2012-08-16 17:54 UTC (permalink / raw)
To: airlied, dri-devel; +Cc: Alex Deucher, stable, David L
From: David L <equinox-freedesktopbugs@diac24.net>
This is required for pure UEFI systems. The vbios is stored
in ACPI rather than at the legacy vga location.
Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=26891
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
---
drivers/gpu/drm/radeon/radeon_bios.c | 59 ++++++++++++++++++++++++++++++++++
1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index 501f488..f06494a7 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -32,6 +32,9 @@
#include <linux/vga_switcheroo.h>
#include <linux/slab.h>
+#ifdef CONFIG_ACPI
+#include <linux/acpi.h>
+#endif
/*
* BIOS.
*/
@@ -476,6 +479,58 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev)
return legacy_read_disabled_bios(rdev);
}
+#ifdef CONFIG_ACPI
+static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+ bool ret = false;
+ struct acpi_table_header *hdr;
+ /* acpi_get_table_with_size is not exported :( */
+ acpi_size tbl_size = 0x7fffffff;
+ UEFI_ACPI_VFCT *vfct;
+ GOP_VBIOS_CONTENT *vbios;
+ VFCT_IMAGE_HEADER *vhdr;
+
+ if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
+ return false;
+ if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
+ DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
+ goto out_unmap;
+ }
+
+ vfct = (UEFI_ACPI_VFCT *)hdr;
+ if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
+ DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
+ goto out_unmap;
+ }
+
+ vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
+ vhdr = &vbios->VbiosHeader;
+ DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
+ vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
+ vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
+
+ if (vhdr->PCIBus != rdev->pdev->bus->number ||
+ vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) ||
+ vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) ||
+ vhdr->VendorID != rdev->pdev->vendor ||
+ vhdr->DeviceID != rdev->pdev->device) {
+ DRM_INFO("ACPI VFCT table is not for this card\n");
+ goto out_unmap;
+ };
+
+ if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
+ DRM_ERROR("ACPI VFCT image truncated\n");
+ goto out_unmap;
+ }
+
+ rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
+ ret = !!rdev->bios;
+
+out_unmap:
+ /* uh, no idea what to do here... */
+ return ret;
+}
+#endif
bool radeon_get_bios(struct radeon_device *rdev)
{
@@ -487,6 +542,10 @@ bool radeon_get_bios(struct radeon_device *rdev)
r = igp_read_bios_from_vram(rdev);
if (r == false)
r = radeon_read_bios(rdev);
+#ifdef CONFIG_ACPI
+ if (r == false)
+ r = radeon_acpi_vfct_bios(rdev);
+#endif
if (r == false) {
r = radeon_read_disabled_bios(rdev);
}
--
1.7.7.5
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler 2012-08-16 17:54 [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch alexdeucher @ 2012-08-16 17:54 ` alexdeucher 2012-08-16 18:26 ` Greg KH 2012-08-16 18:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch Jerome Glisse 2012-08-16 18:25 ` Greg KH 2 siblings, 1 reply; 23+ messages in thread From: alexdeucher @ 2012-08-16 17:54 UTC (permalink / raw) To: airlied, dri-devel; +Cc: Alex Deucher, stable From: Alex Deucher <alexander.deucher@amd.com> There are systems that use ATRM, but not ATPX. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=41265 Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon.h | 15 ----- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 56 +------------------ drivers/gpu/drm/radeon/radeon_bios.c | 79 ++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b70ec30..5dbd591 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -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); /* diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fc..2a2cf0b 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -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; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index f06494a7..c36659a 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -101,16 +101,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; + + /* 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 (!radeon_atrm_supported(rdev->pdev)) + if (!found) return false; rdev->bios = kmalloc(size, GFP_KERNEL); @@ -120,9 +185,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; } @@ -133,6 +199,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } return true; } +#endif static bool ni_read_disabled_bios(struct radeon_device *rdev) { @@ -534,10 +601,12 @@ out_unmap: bool radeon_get_bios(struct radeon_device *rdev) { - bool r; + bool r = false; uint16_t tmp; +#ifdef CONFIG_ACPI r = radeon_atrm_get_bios(rdev); +#endif if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler 2012-08-16 17:54 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler alexdeucher @ 2012-08-16 18:26 ` Greg KH 0 siblings, 0 replies; 23+ messages in thread From: Greg KH @ 2012-08-16 18:26 UTC (permalink / raw) To: alexdeucher; +Cc: Alex Deucher, stable, dri-devel On Thu, Aug 16, 2012 at 01:54:56PM -0400, alexdeucher@gmail.com wrote: > From: Alex Deucher <alexander.deucher@amd.com> > > There are systems that use ATRM, but not ATPX. > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=41265 Same #ifdef comments here as for patch 1/2. thanks, greg k-h ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch 2012-08-16 17:54 [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch alexdeucher 2012-08-16 17:54 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler alexdeucher @ 2012-08-16 18:25 ` Jerome Glisse 2012-08-16 18:25 ` Greg KH 2 siblings, 0 replies; 23+ messages in thread From: Jerome Glisse @ 2012-08-16 18:25 UTC (permalink / raw) To: alexdeucher; +Cc: Alex Deucher, stable, dri-devel, David L On Thu, Aug 16, 2012 at 1:54 PM, <alexdeucher@gmail.com> wrote: > From: David L <equinox-freedesktopbugs@diac24.net> > > This is required for pure UEFI systems. The vbios is stored > in ACPI rather than at the legacy vga location. > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=26891 > > Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Jerome Glisse <jglisse@redhat.com> > Cc: stable@vger.kernel.org > --- > drivers/gpu/drm/radeon/radeon_bios.c | 59 ++++++++++++++++++++++++++++++++++ > 1 files changed, 59 insertions(+), 0 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c > index 501f488..f06494a7 100644 > --- a/drivers/gpu/drm/radeon/radeon_bios.c > +++ b/drivers/gpu/drm/radeon/radeon_bios.c > @@ -32,6 +32,9 @@ > > #include <linux/vga_switcheroo.h> > #include <linux/slab.h> > +#ifdef CONFIG_ACPI > +#include <linux/acpi.h> > +#endif > /* > * BIOS. > */ > @@ -476,6 +479,58 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) > return legacy_read_disabled_bios(rdev); > } > > +#ifdef CONFIG_ACPI > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > +{ > + bool ret = false; > + struct acpi_table_header *hdr; > + /* acpi_get_table_with_size is not exported :( */ > + acpi_size tbl_size = 0x7fffffff; > + UEFI_ACPI_VFCT *vfct; > + GOP_VBIOS_CONTENT *vbios; > + VFCT_IMAGE_HEADER *vhdr; > + > + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) > + return false; > + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); > + goto out_unmap; > + } > + > + vfct = (UEFI_ACPI_VFCT *)hdr; > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); > + goto out_unmap; > + } > + > + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); > + vhdr = &vbios->VbiosHeader; > + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", > + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, > + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); > + > + if (vhdr->PCIBus != rdev->pdev->bus->number || > + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || > + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || > + vhdr->VendorID != rdev->pdev->vendor || > + vhdr->DeviceID != rdev->pdev->device) { > + DRM_INFO("ACPI VFCT table is not for this card\n"); > + goto out_unmap; > + }; > + > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { > + DRM_ERROR("ACPI VFCT image truncated\n"); > + goto out_unmap; > + } > + > + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); > + ret = !!rdev->bios; > + > +out_unmap: > + /* uh, no idea what to do here... */ > + return ret; > +} > +#endif > > bool radeon_get_bios(struct radeon_device *rdev) > { > @@ -487,6 +542,10 @@ bool radeon_get_bios(struct radeon_device *rdev) > r = igp_read_bios_from_vram(rdev); > if (r == false) > r = radeon_read_bios(rdev); > +#ifdef CONFIG_ACPI > + if (r == false) > + r = radeon_acpi_vfct_bios(rdev); > +#endif > if (r == false) { > r = radeon_read_disabled_bios(rdev); > } > -- > 1.7.7.5 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch 2012-08-16 17:54 [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch alexdeucher 2012-08-16 17:54 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler alexdeucher 2012-08-16 18:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch Jerome Glisse @ 2012-08-16 18:25 ` Greg KH 2012-08-16 19:13 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) alexdeucher 2 siblings, 1 reply; 23+ messages in thread From: Greg KH @ 2012-08-16 18:25 UTC (permalink / raw) To: alexdeucher; +Cc: Alex Deucher, stable, dri-devel, David L On Thu, Aug 16, 2012 at 01:54:55PM -0400, alexdeucher@gmail.com wrote: > From: David L <equinox-freedesktopbugs@diac24.net> > > This is required for pure UEFI systems. The vbios is stored > in ACPI rather than at the legacy vga location. > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=26891 > > Signed-off-by: Alex Deucher <alexander.deucher@amd.com> > Cc: stable@vger.kernel.org > --- > drivers/gpu/drm/radeon/radeon_bios.c | 59 ++++++++++++++++++++++++++++++++++ > 1 files changed, 59 insertions(+), 0 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c > index 501f488..f06494a7 100644 > --- a/drivers/gpu/drm/radeon/radeon_bios.c > +++ b/drivers/gpu/drm/radeon/radeon_bios.c > @@ -32,6 +32,9 @@ > > #include <linux/vga_switcheroo.h> > #include <linux/slab.h> > +#ifdef CONFIG_ACPI > +#include <linux/acpi.h> > +#endif This #ifdef should not be needed, right? > +#ifdef CONFIG_ACPI > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > +{ > + bool ret = false; > + struct acpi_table_header *hdr; > + /* acpi_get_table_with_size is not exported :( */ > + acpi_size tbl_size = 0x7fffffff; > + UEFI_ACPI_VFCT *vfct; > + GOP_VBIOS_CONTENT *vbios; > + VFCT_IMAGE_HEADER *vhdr; > + > + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) > + return false; > + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); > + goto out_unmap; > + } > + > + vfct = (UEFI_ACPI_VFCT *)hdr; > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); > + goto out_unmap; > + } > + > + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); > + vhdr = &vbios->VbiosHeader; > + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", > + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, > + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); > + > + if (vhdr->PCIBus != rdev->pdev->bus->number || > + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || > + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || > + vhdr->VendorID != rdev->pdev->vendor || > + vhdr->DeviceID != rdev->pdev->device) { > + DRM_INFO("ACPI VFCT table is not for this card\n"); > + goto out_unmap; > + }; > + > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { > + DRM_ERROR("ACPI VFCT image truncated\n"); > + goto out_unmap; > + } > + > + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); > + ret = !!rdev->bios; > + > +out_unmap: > + /* uh, no idea what to do here... */ > + return ret; > +} > +#endif Please provide an "empty" function here if the #ifdef is not true, which then makes the following #ifdef not needed: > @@ -487,6 +542,10 @@ bool radeon_get_bios(struct radeon_device *rdev) > r = igp_read_bios_from_vram(rdev); > if (r == false) > r = radeon_read_bios(rdev); > +#ifdef CONFIG_ACPI > + if (r == false) > + r = radeon_acpi_vfct_bios(rdev); > +#endif See, then that #ifdef isn't needed. That cleans up the code more, remember, we don't want #ifdefs in .c files unless we _really_ have to have them. thanks, greg k-h ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) 2012-08-16 18:25 ` Greg KH @ 2012-08-16 19:13 ` alexdeucher 2012-08-16 19:13 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v2) alexdeucher ` (2 more replies) 0 siblings, 3 replies; 23+ messages in thread From: alexdeucher @ 2012-08-16 19:13 UTC (permalink / raw) To: airlied, dri-devel; +Cc: Alex Deucher, stable, David L From: David L <equinox-freedesktopbugs@diac24.net> This is required for pure UEFI systems. The vbios is stored in ACPI rather than at the legacy vga location. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26891 V2: fix #ifdefs as per Greg's comments Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_bios.c | 62 ++++++++++++++++++++++++++++++++++ 1 files changed, 62 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f488..bf21f65 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,9 @@ #include <linux/vga_switcheroo.h> #include <linux/slab.h> +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#endif /* * BIOS. */ @@ -476,6 +479,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + struct acpi_table_header *hdr; + /* acpi_get_table_with_size is not exported :( */ + acpi_size tbl_size = 0x7fffffff; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->pdev->bus->number || + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || + vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + ret = !!rdev->bios; + +out_unmap: + /* uh, no idea what to do here... */ + return ret; +} +#else +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -484,6 +544,8 @@ bool radeon_get_bios(struct radeon_device *rdev) r = radeon_atrm_get_bios(rdev); if (r == false) + r = radeon_acpi_vfct_bios(rdev); + if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) r = radeon_read_bios(rdev); -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v2) 2012-08-16 19:13 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) alexdeucher @ 2012-08-16 19:13 ` alexdeucher 2012-08-16 19:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) Greg KH 2012-08-16 19:40 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) David Lamparter 2 siblings, 0 replies; 23+ messages in thread From: alexdeucher @ 2012-08-16 19:13 UTC (permalink / raw) To: airlied, dri-devel; +Cc: Alex Deucher, stable From: Alex Deucher <alexander.deucher@amd.com> 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 Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon.h | 15 ----- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 56 +----------------- drivers/gpu/drm/radeon/radeon_bios.c | 82 ++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9930419..59a1531 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -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); /* diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fc..2a2cf0b 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -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; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index bf21f65..e97779d 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,9 +32,7 @@ #include <linux/vga_switcheroo.h> #include <linux/slab.h> -#ifdef CONFIG_ACPI #include <linux/acpi.h> -#endif /* * BIOS. */ @@ -101,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; + + /* 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 (!radeon_atrm_supported(rdev->pdev)) + if (!found) return false; rdev->bios = kmalloc(size, GFP_KERNEL); @@ -120,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; } @@ -133,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } return true; } +#else +static bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + return false; +} +#endif static bool ni_read_disabled_bios(struct radeon_device *rdev) { -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) 2012-08-16 19:13 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) alexdeucher 2012-08-16 19:13 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v2) alexdeucher @ 2012-08-16 19:25 ` Greg KH 2012-08-16 19:38 ` Alex Deucher 2012-08-16 19:48 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher 2012-08-16 19:40 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) David Lamparter 2 siblings, 2 replies; 23+ messages in thread From: Greg KH @ 2012-08-16 19:25 UTC (permalink / raw) To: alexdeucher; +Cc: Alex Deucher, stable, dri-devel, David L On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: > From: David L <equinox-freedesktopbugs@diac24.net> > > This is required for pure UEFI systems. The vbios is stored > in ACPI rather than at the legacy vga location. > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=26891 > > V2: fix #ifdefs as per Greg's comments > > Signed-off-by: Alex Deucher <alexander.deucher@amd.com> > Cc: stable@vger.kernel.org > --- > drivers/gpu/drm/radeon/radeon_bios.c | 62 ++++++++++++++++++++++++++++++++++ > 1 files changed, 62 insertions(+), 0 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c > index 501f488..bf21f65 100644 > --- a/drivers/gpu/drm/radeon/radeon_bios.c > +++ b/drivers/gpu/drm/radeon/radeon_bios.c > @@ -32,6 +32,9 @@ > > #include <linux/vga_switcheroo.h> > #include <linux/slab.h> > +#ifdef CONFIG_ACPI > +#include <linux/acpi.h> > +#endif You forgot to remove this one :( > /* > * BIOS. > */ > @@ -476,6 +479,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) > return legacy_read_disabled_bios(rdev); > } > > +#ifdef CONFIG_ACPI > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > +{ > + bool ret = false; > + struct acpi_table_header *hdr; > + /* acpi_get_table_with_size is not exported :( */ > + acpi_size tbl_size = 0x7fffffff; > + UEFI_ACPI_VFCT *vfct; > + GOP_VBIOS_CONTENT *vbios; > + VFCT_IMAGE_HEADER *vhdr; > + > + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) > + return false; > + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); > + goto out_unmap; > + } > + > + vfct = (UEFI_ACPI_VFCT *)hdr; > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); > + goto out_unmap; > + } > + > + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); > + vhdr = &vbios->VbiosHeader; > + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", > + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, > + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); > + > + if (vhdr->PCIBus != rdev->pdev->bus->number || > + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || > + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || > + vhdr->VendorID != rdev->pdev->vendor || > + vhdr->DeviceID != rdev->pdev->device) { > + DRM_INFO("ACPI VFCT table is not for this card\n"); > + goto out_unmap; > + }; > + > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { > + DRM_ERROR("ACPI VFCT image truncated\n"); > + goto out_unmap; > + } > + > + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); > + ret = !!rdev->bios; > + > +out_unmap: > + /* uh, no idea what to do here... */ > + return ret; > +} > +#else > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) Make it inline, and then the compiler is smart enough to just delete the whole if () check you make when you call it. Third time's a charm? greg k-h ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) 2012-08-16 19:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) Greg KH @ 2012-08-16 19:38 ` Alex Deucher 2012-08-16 19:48 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher 1 sibling, 0 replies; 23+ messages in thread From: Alex Deucher @ 2012-08-16 19:38 UTC (permalink / raw) To: Greg KH; +Cc: Alex Deucher, stable, dri-devel, David L On Thu, Aug 16, 2012 at 3:25 PM, Greg KH <gregkh@linuxfoundation.org> wrote: > On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: >> From: David L <equinox-freedesktopbugs@diac24.net> >> >> This is required for pure UEFI systems. The vbios is stored >> in ACPI rather than at the legacy vga location. >> >> Fixes: >> https://bugs.freedesktop.org/show_bug.cgi?id=26891 >> >> V2: fix #ifdefs as per Greg's comments >> >> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >> Cc: stable@vger.kernel.org >> --- >> drivers/gpu/drm/radeon/radeon_bios.c | 62 ++++++++++++++++++++++++++++++++++ >> 1 files changed, 62 insertions(+), 0 deletions(-) >> >> diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c >> index 501f488..bf21f65 100644 >> --- a/drivers/gpu/drm/radeon/radeon_bios.c >> +++ b/drivers/gpu/drm/radeon/radeon_bios.c >> @@ -32,6 +32,9 @@ >> >> #include <linux/vga_switcheroo.h> >> #include <linux/slab.h> >> +#ifdef CONFIG_ACPI >> +#include <linux/acpi.h> >> +#endif > > You forgot to remove this one :( Argh! I squashed that into the wrong patch when I rebased my fixes. > >> /* >> * BIOS. >> */ >> @@ -476,6 +479,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) >> return legacy_read_disabled_bios(rdev); >> } >> >> +#ifdef CONFIG_ACPI >> +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) >> +{ >> + bool ret = false; >> + struct acpi_table_header *hdr; >> + /* acpi_get_table_with_size is not exported :( */ >> + acpi_size tbl_size = 0x7fffffff; >> + UEFI_ACPI_VFCT *vfct; >> + GOP_VBIOS_CONTENT *vbios; >> + VFCT_IMAGE_HEADER *vhdr; >> + >> + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) >> + return false; >> + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); >> + goto out_unmap; >> + } >> + >> + vfct = (UEFI_ACPI_VFCT *)hdr; >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); >> + goto out_unmap; >> + } >> + >> + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); >> + vhdr = &vbios->VbiosHeader; >> + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", >> + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, >> + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); >> + >> + if (vhdr->PCIBus != rdev->pdev->bus->number || >> + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || >> + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || >> + vhdr->VendorID != rdev->pdev->vendor || >> + vhdr->DeviceID != rdev->pdev->device) { >> + DRM_INFO("ACPI VFCT table is not for this card\n"); >> + goto out_unmap; >> + }; >> + >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { >> + DRM_ERROR("ACPI VFCT image truncated\n"); >> + goto out_unmap; >> + } >> + >> + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); >> + ret = !!rdev->bios; >> + >> +out_unmap: >> + /* uh, no idea what to do here... */ >> + return ret; >> +} >> +#else >> +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > > Make it inline, and then the compiler is smart enough to just delete the > whole if () check you make when you call it. > > Third time's a charm? On the way. Alex ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v3) 2012-08-16 19:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) Greg KH 2012-08-16 19:38 ` Alex Deucher @ 2012-08-16 19:48 ` alexdeucher 2012-08-16 19:48 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v3) alexdeucher 1 sibling, 1 reply; 23+ messages in thread From: alexdeucher @ 2012-08-16 19:48 UTC (permalink / raw) To: airlied, dri-devel; +Cc: Alex Deucher, stable From: David Lamparter <equinox@diac24.net> This is required for pure UEFI systems. The vbios is stored in ACPI rather than at the legacy vga location. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26891 V2: fix #ifdefs as per Greg's comments V3: fix it harder Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Jerome Glisse <jglisse@redhat.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_bios.c | 60 ++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f488..a32232f 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,7 @@ #include <linux/vga_switcheroo.h> #include <linux/slab.h> +#include <linux/acpi.h> /* * BIOS. */ @@ -476,6 +477,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + struct acpi_table_header *hdr; + /* acpi_get_table_with_size is not exported :( */ + acpi_size tbl_size = 0x7fffffff; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->pdev->bus->number || + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || + vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + ret = !!rdev->bios; + +out_unmap: + /* uh, no idea what to do here... */ + return ret; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -484,6 +542,8 @@ bool radeon_get_bios(struct radeon_device *rdev) r = radeon_atrm_get_bios(rdev); if (r == false) + r = radeon_acpi_vfct_bios(rdev); + if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) r = radeon_read_bios(rdev); -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v3) 2012-08-16 19:48 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher @ 2012-08-16 19:48 ` alexdeucher 0 siblings, 0 replies; 23+ messages in thread From: alexdeucher @ 2012-08-16 19:48 UTC (permalink / raw) To: airlied, dri-devel; +Cc: Alex Deucher, stable From: Alex Deucher <alexander.deucher@amd.com> 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 --- drivers/gpu/drm/radeon/radeon.h | 15 ----- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 56 +------------------ drivers/gpu/drm/radeon/radeon_bios.c | 80 ++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9930419..59a1531 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -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); /* diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fc..2a2cf0b 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -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; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index a32232f..602898d 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -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) { -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) 2012-08-16 19:13 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) alexdeucher 2012-08-16 19:13 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v2) alexdeucher 2012-08-16 19:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) Greg KH @ 2012-08-16 19:40 ` David Lamparter 2012-08-16 19:51 ` Alex Deucher 2 siblings, 1 reply; 23+ messages in thread From: David Lamparter @ 2012-08-16 19:40 UTC (permalink / raw) To: alexdeucher; +Cc: Alex Deucher, stable, dri-devel, David L [-- Attachment #1.1: Type: text/plain, Size: 3318 bytes --] On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: > From: David L <equinox-freedesktopbugs@diac24.net> From: David Lamparter <equinox@diac24.net> There are still two rough edges left in here, I didn't get around to clean it up, other stuff came up -- sorry... > This is required for pure UEFI systems. The vbios is stored > in ACPI rather than at the legacy vga location. > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=26891 > > V2: fix #ifdefs as per Greg's comments > > Signed-off-by: Alex Deucher <alexander.deucher@amd.com> > Cc: stable@vger.kernel.org > --- [...] > + struct acpi_table_header *hdr; > + /* acpi_get_table_with_size is not exported :( */ > + acpi_size tbl_size = 0x7fffffff; I was using acpi_get_table_with_size, but that needs an export, with 0x7fffffff all the tests below are kinda useless because they always succeed. I think it'd be useful to keep the length checks in case some vendor breaks their ACPI tables, so this needs an EXPORT_SYMBOL. > + UEFI_ACPI_VFCT *vfct; > + GOP_VBIOS_CONTENT *vbios; > + VFCT_IMAGE_HEADER *vhdr; > + > + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) > + return false; > + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); > + goto out_unmap; > + } > + > + vfct = (UEFI_ACPI_VFCT *)hdr; > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { > + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); > + goto out_unmap; > + } > + > + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); > + vhdr = &vbios->VbiosHeader; > + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", > + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, > + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); > + > + if (vhdr->PCIBus != rdev->pdev->bus->number || > + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || > + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || > + vhdr->VendorID != rdev->pdev->vendor || > + vhdr->DeviceID != rdev->pdev->device) { > + DRM_INFO("ACPI VFCT table is not for this card\n"); > + goto out_unmap; > + }; > + > + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { > + DRM_ERROR("ACPI VFCT image truncated\n"); > + goto out_unmap; > + } > + > + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); > + ret = !!rdev->bios; > + > +out_unmap: > + /* uh, no idea what to do here... */ So, er, I had no clue how to clean up the return value of acpi_get_table - does this actually need to be cleaned up? Or do you just get a pointer straight to the "real" ACPI table? > + return ret; > +} > +#else > +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) > +{ > + return false; > +} > +#endif > > bool radeon_get_bios(struct radeon_device *rdev) > { > @@ -484,6 +544,8 @@ bool radeon_get_bios(struct radeon_device *rdev) > > r = radeon_atrm_get_bios(rdev); > if (r == false) > + r = radeon_acpi_vfct_bios(rdev); > + if (r == false) > r = igp_read_bios_from_vram(rdev); > if (r == false) > r = radeon_read_bios(rdev); > -- > 1.7.7.5 > Cheers, -David [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 230 bytes --] [-- Attachment #2: Type: text/plain, Size: 159 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) 2012-08-16 19:40 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) David Lamparter @ 2012-08-16 19:51 ` Alex Deucher 2012-08-17 16:56 ` Alex Deucher 0 siblings, 1 reply; 23+ messages in thread From: Alex Deucher @ 2012-08-16 19:51 UTC (permalink / raw) To: David Lamparter; +Cc: Alex Deucher, stable, dri-devel, David L On Thu, Aug 16, 2012 at 3:40 PM, David Lamparter <equinox@diac24.net> wrote: > On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: >> From: David L <equinox-freedesktopbugs@diac24.net> > From: David Lamparter <equinox@diac24.net> > > There are still two rough edges left in here, I didn't get around to > clean it up, other stuff came up -- sorry... > >> This is required for pure UEFI systems. The vbios is stored >> in ACPI rather than at the legacy vga location. >> >> Fixes: >> https://bugs.freedesktop.org/show_bug.cgi?id=26891 >> >> V2: fix #ifdefs as per Greg's comments >> >> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >> Cc: stable@vger.kernel.org >> --- > [...] >> + struct acpi_table_header *hdr; >> + /* acpi_get_table_with_size is not exported :( */ >> + acpi_size tbl_size = 0x7fffffff; > > I was using acpi_get_table_with_size, but that needs an export, with > 0x7fffffff all the tests below are kinda useless because they always > succeed. I think it'd be useful to keep the length checks in case some > vendor breaks their ACPI tables, so this needs an EXPORT_SYMBOL. I guess we could leave it as is for now for -fixes and then switch it use use the new exported symbol for -next? Is it ok to export a new symbol for -fixes? > >> + UEFI_ACPI_VFCT *vfct; >> + GOP_VBIOS_CONTENT *vbios; >> + VFCT_IMAGE_HEADER *vhdr; >> + >> + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) >> + return false; >> + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); >> + goto out_unmap; >> + } >> + >> + vfct = (UEFI_ACPI_VFCT *)hdr; >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { >> + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); >> + goto out_unmap; >> + } >> + >> + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); >> + vhdr = &vbios->VbiosHeader; >> + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", >> + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, >> + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); >> + >> + if (vhdr->PCIBus != rdev->pdev->bus->number || >> + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || >> + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || >> + vhdr->VendorID != rdev->pdev->vendor || >> + vhdr->DeviceID != rdev->pdev->device) { >> + DRM_INFO("ACPI VFCT table is not for this card\n"); >> + goto out_unmap; >> + }; >> + >> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { >> + DRM_ERROR("ACPI VFCT image truncated\n"); >> + goto out_unmap; >> + } >> + >> + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); >> + ret = !!rdev->bios; >> + >> +out_unmap: >> + /* uh, no idea what to do here... */ > > So, er, I had no clue how to clean up the return value of acpi_get_table > - does this actually need to be cleaned up? Or do you just get a > pointer straight to the "real" ACPI table? Not sure on that. Anyone know more about the acpi code? Alex ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) 2012-08-16 19:51 ` Alex Deucher @ 2012-08-17 16:56 ` Alex Deucher 2012-08-17 17:03 ` Matthew Garrett 0 siblings, 1 reply; 23+ messages in thread From: Alex Deucher @ 2012-08-17 16:56 UTC (permalink / raw) To: David Lamparter; +Cc: stable, dri-devel, David L, Alex Deucher, Matthew Garrett Adding Matthew in case he as any ideas. On Thu, Aug 16, 2012 at 3:51 PM, Alex Deucher <alexdeucher@gmail.com> wrote: > On Thu, Aug 16, 2012 at 3:40 PM, David Lamparter <equinox@diac24.net> wrote: >> On Thu, Aug 16, 2012 at 03:13:46PM -0400, alexdeucher@gmail.com wrote: >>> From: David L <equinox-freedesktopbugs@diac24.net> >> From: David Lamparter <equinox@diac24.net> >> >> There are still two rough edges left in here, I didn't get around to >> clean it up, other stuff came up -- sorry... >> >>> This is required for pure UEFI systems. The vbios is stored >>> in ACPI rather than at the legacy vga location. >>> >>> Fixes: >>> https://bugs.freedesktop.org/show_bug.cgi?id=26891 >>> >>> V2: fix #ifdefs as per Greg's comments >>> >>> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >>> Cc: stable@vger.kernel.org >>> --- >> [...] >>> + struct acpi_table_header *hdr; >>> + /* acpi_get_table_with_size is not exported :( */ >>> + acpi_size tbl_size = 0x7fffffff; >> >> I was using acpi_get_table_with_size, but that needs an export, with >> 0x7fffffff all the tests below are kinda useless because they always >> succeed. I think it'd be useful to keep the length checks in case some >> vendor breaks their ACPI tables, so this needs an EXPORT_SYMBOL. > > I guess we could leave it as is for now for -fixes and then switch it > use use the new exported symbol for -next? Is it ok to export a new > symbol for -fixes? > >> >>> + UEFI_ACPI_VFCT *vfct; >>> + GOP_VBIOS_CONTENT *vbios; >>> + VFCT_IMAGE_HEADER *vhdr; >>> + >>> + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) >>> + return false; >>> + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { >>> + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); >>> + goto out_unmap; >>> + } >>> + >>> + vfct = (UEFI_ACPI_VFCT *)hdr; >>> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { >>> + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); >>> + goto out_unmap; >>> + } >>> + >>> + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); >>> + vhdr = &vbios->VbiosHeader; >>> + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", >>> + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, >>> + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); >>> + >>> + if (vhdr->PCIBus != rdev->pdev->bus->number || >>> + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || >>> + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || >>> + vhdr->VendorID != rdev->pdev->vendor || >>> + vhdr->DeviceID != rdev->pdev->device) { >>> + DRM_INFO("ACPI VFCT table is not for this card\n"); >>> + goto out_unmap; >>> + }; >>> + >>> + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { >>> + DRM_ERROR("ACPI VFCT image truncated\n"); >>> + goto out_unmap; >>> + } >>> + >>> + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); >>> + ret = !!rdev->bios; >>> + >>> +out_unmap: >>> + /* uh, no idea what to do here... */ >> >> So, er, I had no clue how to clean up the return value of acpi_get_table >> - does this actually need to be cleaned up? Or do you just get a >> pointer straight to the "real" ACPI table? > > Not sure on that. Anyone know more about the acpi code? > > Alex ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) 2012-08-17 16:56 ` Alex Deucher @ 2012-08-17 17:03 ` Matthew Garrett 2012-08-20 15:19 ` [PATCH 1/4] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher 0 siblings, 1 reply; 23+ messages in thread From: Matthew Garrett @ 2012-08-17 17:03 UTC (permalink / raw) To: Alex Deucher; +Cc: stable, dri-devel, David L, Alex Deucher On Fri, Aug 17, 2012 at 12:56:31PM -0400, Alex Deucher wrote: > > I guess we could leave it as is for now for -fixes and then switch it > > use use the new exported symbol for -next? Is it ok to export a new > > symbol for -fixes? I don't see why not, providing the ACPI people are happy with it. > >> So, er, I had no clue how to clean up the return value of acpi_get_table > >> - does this actually need to be cleaned up? Or do you just get a > >> pointer straight to the "real" ACPI table? > > > > Not sure on that. Anyone know more about the acpi code? Not sure what you're asking here - acpi_get_table returns acpi_status, not a pointer. -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 1/4] drm/radeon: implement ACPI VFCT vbios fetch (v3) 2012-08-17 17:03 ` Matthew Garrett @ 2012-08-20 15:19 ` alexdeucher 2012-08-20 15:19 ` [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size alexdeucher ` (2 more replies) 0 siblings, 3 replies; 23+ messages in thread From: alexdeucher @ 2012-08-20 15:19 UTC (permalink / raw) To: airlied, dri-devel, equinox; +Cc: linux-acpi, Alex Deucher, stable From: David Lamparter <equinox@diac24.net> This is required for pure UEFI systems. The vbios is stored in ACPI rather than at the legacy vga location. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26891 V2: fix #ifdefs as per Greg's comments V3: fix it harder Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Jerome Glisse <jglisse@redhat.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_bios.c | 60 ++++++++++++++++++++++++++++++++++ 1 files changed, 60 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f488..a32232f 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,7 @@ #include <linux/vga_switcheroo.h> #include <linux/slab.h> +#include <linux/acpi.h> /* * BIOS. */ @@ -476,6 +477,63 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + struct acpi_table_header *hdr; + /* acpi_get_table_with_size is not exported :( */ + acpi_size tbl_size = 0x7fffffff; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->pdev->bus->number || + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || + vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + ret = !!rdev->bios; + +out_unmap: + /* uh, no idea what to do here... */ + return ret; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -484,6 +542,8 @@ bool radeon_get_bios(struct radeon_device *rdev) r = radeon_atrm_get_bios(rdev); if (r == false) + r = radeon_acpi_vfct_bios(rdev); + if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) r = radeon_read_bios(rdev); -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size 2012-08-20 15:19 ` [PATCH 1/4] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher @ 2012-08-20 15:19 ` alexdeucher 2012-08-21 14:50 ` Alex Deucher 2012-08-20 15:19 ` [PATCH 3/4] drm/radeon: convert radeon vfct code to use acpi_get_table_with_size alexdeucher 2012-08-20 15:19 ` [PATCH 4/4] drm/radeon: split ATRM support out from the ATPX handler (v3) alexdeucher 2 siblings, 1 reply; 23+ messages in thread From: alexdeucher @ 2012-08-20 15:19 UTC (permalink / raw) To: airlied, dri-devel, equinox; +Cc: linux-acpi, Alex Deucher, stable From: Alex Deucher <alexander.deucher@amd.com> We need it in the radeon drm module to fetch and verify the vbios image on UEFI systems. Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org --- drivers/acpi/acpica/tbxface.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ea4c6d5..29e51bc 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -387,6 +387,7 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) acpi_status acpi_get_table(char *signature, -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size 2012-08-20 15:19 ` [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size alexdeucher @ 2012-08-21 14:50 ` Alex Deucher 2012-08-21 14:51 ` Matthew Garrett ` (2 more replies) 0 siblings, 3 replies; 23+ messages in thread From: Alex Deucher @ 2012-08-21 14:50 UTC (permalink / raw) To: airlied, dri-devel, equinox Cc: linux-acpi, Alex Deucher, stable, Matthew Garrett Any objections from the ACPI folks to this patch going into 3.6 and stable? Alex On Mon, Aug 20, 2012 at 11:19 AM, <alexdeucher@gmail.com> wrote: > From: Alex Deucher <alexander.deucher@amd.com> > > We need it in the radeon drm module to fetch > and verify the vbios image on UEFI systems. > > Signed-off-by: Alex Deucher <alexander.deucher@amd.com> > Cc: stable@vger.kernel.org > --- > drivers/acpi/acpica/tbxface.c | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c > index ea4c6d5..29e51bc 100644 > --- a/drivers/acpi/acpica/tbxface.c > +++ b/drivers/acpi/acpica/tbxface.c > @@ -387,6 +387,7 @@ acpi_get_table_with_size(char *signature, > > return (AE_NOT_FOUND); > } > +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) > > acpi_status > acpi_get_table(char *signature, > -- > 1.7.7.5 > ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size 2012-08-21 14:50 ` Alex Deucher @ 2012-08-21 14:51 ` Matthew Garrett 2012-08-21 14:52 ` Matthew Garrett 2012-08-22 8:31 ` Lan Tianyu 2 siblings, 0 replies; 23+ messages in thread From: Matthew Garrett @ 2012-08-21 14:51 UTC (permalink / raw) To: Alex Deucher Cc: airlied, dri-devel, equinox, linux-acpi, Alex Deucher, stable -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size 2012-08-21 14:50 ` Alex Deucher 2012-08-21 14:51 ` Matthew Garrett @ 2012-08-21 14:52 ` Matthew Garrett 2012-08-22 8:31 ` Lan Tianyu 2 siblings, 0 replies; 23+ messages in thread From: Matthew Garrett @ 2012-08-21 14:52 UTC (permalink / raw) To: Alex Deucher Cc: airlied, dri-devel, equinox, linux-acpi, Alex Deucher, stable On Tue, Aug 21, 2012 at 10:50:35AM -0400, Alex Deucher wrote: > Any objections from the ACPI folks to this patch going into 3.6 and stable? Looks good to me. -- Matthew Garrett | mjg59@srcf.ucam.org ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size 2012-08-21 14:50 ` Alex Deucher 2012-08-21 14:51 ` Matthew Garrett 2012-08-21 14:52 ` Matthew Garrett @ 2012-08-22 8:31 ` Lan Tianyu 2 siblings, 0 replies; 23+ messages in thread From: Lan Tianyu @ 2012-08-22 8:31 UTC (permalink / raw) To: Alex Deucher Cc: airlied, dri-devel, equinox, linux-acpi, Alex Deucher, stable, Matthew Garrett, feng.tang, robert.moore 2012/8/21 Alex Deucher <alexdeucher@gmail.com>: > Any objections from the ACPI folks to this patch going into 3.6 and stable? > hi Alex: I saw the patch from Feng Tang. http://marc.info/?l=linux-acpi&m=134380363332502&w=2 which is trying to replace acpi_get_table_with_size() with acpi_get_table(). Since the size can be get via struct acpi_table_header->length, acpi_get_table_with_size() is redundant and it will be removed. > Alex > > On Mon, Aug 20, 2012 at 11:19 AM, <alexdeucher@gmail.com> wrote: >> From: Alex Deucher <alexander.deucher@amd.com> >> >> We need it in the radeon drm module to fetch >> and verify the vbios image on UEFI systems. >> >> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> >> Cc: stable@vger.kernel.org >> --- >> drivers/acpi/acpica/tbxface.c | 1 + >> 1 files changed, 1 insertions(+), 0 deletions(-) >> >> diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c >> index ea4c6d5..29e51bc 100644 >> --- a/drivers/acpi/acpica/tbxface.c >> +++ b/drivers/acpi/acpica/tbxface.c >> @@ -387,6 +387,7 @@ acpi_get_table_with_size(char *signature, >> >> return (AE_NOT_FOUND); >> } >> +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) >> >> acpi_status >> acpi_get_table(char *signature, >> -- >> 1.7.7.5 >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- Best regards Tianyu Lan ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 3/4] drm/radeon: convert radeon vfct code to use acpi_get_table_with_size 2012-08-20 15:19 ` [PATCH 1/4] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher 2012-08-20 15:19 ` [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size alexdeucher @ 2012-08-20 15:19 ` alexdeucher 2012-08-20 15:19 ` [PATCH 4/4] drm/radeon: split ATRM support out from the ATPX handler (v3) alexdeucher 2 siblings, 0 replies; 23+ messages in thread From: alexdeucher @ 2012-08-20 15:19 UTC (permalink / raw) To: airlied, dri-devel, equinox; +Cc: linux-acpi, Alex Deucher, stable From: Alex Deucher <alexander.deucher@amd.com> Allows us to verify the table size. Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_bios.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index a32232f..ab0b2f7 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -482,13 +482,12 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) { bool ret = false; struct acpi_table_header *hdr; - /* acpi_get_table_with_size is not exported :( */ - acpi_size tbl_size = 0x7fffffff; + acpi_size tbl_size; UEFI_ACPI_VFCT *vfct; GOP_VBIOS_CONTENT *vbios; VFCT_IMAGE_HEADER *vhdr; - if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) return false; if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); @@ -525,7 +524,6 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) ret = !!rdev->bios; out_unmap: - /* uh, no idea what to do here... */ return ret; } #else -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 4/4] drm/radeon: split ATRM support out from the ATPX handler (v3) 2012-08-20 15:19 ` [PATCH 1/4] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher 2012-08-20 15:19 ` [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size alexdeucher 2012-08-20 15:19 ` [PATCH 3/4] drm/radeon: convert radeon vfct code to use acpi_get_table_with_size alexdeucher @ 2012-08-20 15:19 ` alexdeucher 2 siblings, 0 replies; 23+ messages in thread From: alexdeucher @ 2012-08-20 15:19 UTC (permalink / raw) To: airlied, dri-devel, equinox; +Cc: linux-acpi, Alex Deucher, stable From: Alex Deucher <alexander.deucher@amd.com> 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 --- drivers/gpu/drm/radeon/radeon.h | 15 ----- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 56 +------------------ drivers/gpu/drm/radeon/radeon_bios.c | 80 ++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9930419..59a1531 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -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); /* diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fc..2a2cf0b 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -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; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index ab0b2f7..d306cc8 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -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) { -- 1.7.7.5 ^ permalink raw reply related [flat|nested] 23+ messages in thread
end of thread, other threads:[~2012-08-22 8:31 UTC | newest] Thread overview: 23+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-08-16 17:54 [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch alexdeucher 2012-08-16 17:54 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler alexdeucher 2012-08-16 18:26 ` Greg KH 2012-08-16 18:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch Jerome Glisse 2012-08-16 18:25 ` Greg KH 2012-08-16 19:13 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) alexdeucher 2012-08-16 19:13 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v2) alexdeucher 2012-08-16 19:25 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) Greg KH 2012-08-16 19:38 ` Alex Deucher 2012-08-16 19:48 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher 2012-08-16 19:48 ` [PATCH 2/2] drm/radeon: split ATRM support out from the ATPX handler (v3) alexdeucher 2012-08-16 19:40 ` [PATCH 1/2] drm/radeon: implement ACPI VFCT vbios fetch (v2) David Lamparter 2012-08-16 19:51 ` Alex Deucher 2012-08-17 16:56 ` Alex Deucher 2012-08-17 17:03 ` Matthew Garrett 2012-08-20 15:19 ` [PATCH 1/4] drm/radeon: implement ACPI VFCT vbios fetch (v3) alexdeucher 2012-08-20 15:19 ` [PATCH 2/4] ACPI: export symbol acpi_get_table_with_size alexdeucher 2012-08-21 14:50 ` Alex Deucher 2012-08-21 14:51 ` Matthew Garrett 2012-08-21 14:52 ` Matthew Garrett 2012-08-22 8:31 ` Lan Tianyu 2012-08-20 15:19 ` [PATCH 3/4] drm/radeon: convert radeon vfct code to use acpi_get_table_with_size alexdeucher 2012-08-20 15:19 ` [PATCH 4/4] drm/radeon: split ATRM support out from the ATPX handler (v3) alexdeucher
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox