* [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 an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.