mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org, "Mark Kettenis" <kettenis@openbsd.org>,
	"Alex Deucher" <alexander.deucher@amd.com>
Subject: [65/84] drm/radeon: fix combios tables on older cards
Date: Wed, 31 Jul 2013 15:23:09 +0200	[thread overview]
Message-ID: <lsq.1375276989.359885615@decadent.org.uk> (raw)
In-Reply-To: <lsq.1375276989.251749228@decadent.org.uk>

3.2.50-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Mark Kettenis <kettenis@openbsd.org>

commit cef1d00cd56f600121ad121875655ad410a001b8 upstream.

Noticed that my old Radeon 7500 hung after printing

   drm: GPU not posted. posting now...

when it wasn't selected as the primary card the BIOS.  Some digging
revealed that it was hanging in combios_parse_mmio_table() while
parsing the ASIC INIT 3 table.  Looking at the BIOS ROM for the card,
it becomes obvious that there is no ASIC INIT 3 table in the BIOS.
The code is just processing random garbage.  No surprise it hangs!

Why do I say that there is no ASIC INIT 3 table is the BIOS?  This
table is found through the MISC INFO table.  The MISC INFO table can
be found at offset 0x5e in the COMBIOS header.  But the header is
smaller than that.  The COMBIOS header starts at offset 0x126.  The
standard PCI Data Structure (the bit that starts with 'PCIR') lives at
offset 0x180.  That means that the COMBIOS header can not be larger
than 0x5a bytes and therefore cannot contain a MISC INFO table.

I looked at a dozen or so BIOS images, some my own, some downloaded from:

    <http://www.techpowerup.com/vgabios/index.php?manufacturer=ATI&page=1>

It is fairly obvious that the size of the COMBIOS header can be found
at offset 0x6 of the header.  Not sure if it is a 16-bit number or
just an 8-bit number, but that doesn't really matter since the tables
seems to be always smaller than 256 bytes.

So I think combios_get_table_offset() should check if the requested
table is present.  This can be done by checking the offset against the
size of the header.  See the diff below.  The diff is against the WIP
OpenBSD codebase that roughly corresponds to Linux 3.8.13 at this
point.  But I don't think this bit of the code changed much since
then.

For what it is worth:

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/gpu/drm/radeon/radeon_combios.c | 145 +++++++++-----------------------
 1 file changed, 41 insertions(+), 104 deletions(-)

--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -147,7 +147,7 @@ static uint16_t combios_get_table_offset
 					 enum radeon_combios_table_offset table)
 {
 	struct radeon_device *rdev = dev->dev_private;
-	int rev;
+	int rev, size;
 	uint16_t offset = 0, check_offset;
 
 	if (!rdev->bios)
@@ -156,174 +156,106 @@ static uint16_t combios_get_table_offset
 	switch (table) {
 		/* absolute offset tables */
 	case COMBIOS_ASIC_INIT_1_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0xc);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0xc;
 		break;
 	case COMBIOS_BIOS_SUPPORT_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x14);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x14;
 		break;
 	case COMBIOS_DAC_PROGRAMMING_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x2a);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x2a;
 		break;
 	case COMBIOS_MAX_COLOR_DEPTH_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x2c);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x2c;
 		break;
 	case COMBIOS_CRTC_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x2e);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x2e;
 		break;
 	case COMBIOS_PLL_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x30);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x30;
 		break;
 	case COMBIOS_TV_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x32);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x32;
 		break;
 	case COMBIOS_DFP_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x34);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x34;
 		break;
 	case COMBIOS_HW_CONFIG_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x36);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x36;
 		break;
 	case COMBIOS_MULTIMEDIA_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x38);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x38;
 		break;
 	case COMBIOS_TV_STD_PATCH_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x3e);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x3e;
 		break;
 	case COMBIOS_LCD_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x40);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x40;
 		break;
 	case COMBIOS_MOBILE_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x42);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x42;
 		break;
 	case COMBIOS_PLL_INIT_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x46);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x46;
 		break;
 	case COMBIOS_MEM_CONFIG_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x48);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x48;
 		break;
 	case COMBIOS_SAVE_MASK_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x4a);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x4a;
 		break;
 	case COMBIOS_HARDCODED_EDID_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x4c);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x4c;
 		break;
 	case COMBIOS_ASIC_INIT_2_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x4e);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x4e;
 		break;
 	case COMBIOS_CONNECTOR_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x50);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x50;
 		break;
 	case COMBIOS_DYN_CLK_1_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x52);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x52;
 		break;
 	case COMBIOS_RESERVED_MEM_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x54);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x54;
 		break;
 	case COMBIOS_EXT_TMDS_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x58);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x58;
 		break;
 	case COMBIOS_MEM_CLK_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x5a);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x5a;
 		break;
 	case COMBIOS_EXT_DAC_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x5c);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x5c;
 		break;
 	case COMBIOS_MISC_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x5e);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x5e;
 		break;
 	case COMBIOS_CRT_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x60);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x60;
 		break;
 	case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x62);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x62;
 		break;
 	case COMBIOS_COMPONENT_VIDEO_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x64);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x64;
 		break;
 	case COMBIOS_FAN_SPEED_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x66);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x66;
 		break;
 	case COMBIOS_OVERDRIVE_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x68);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x68;
 		break;
 	case COMBIOS_OEM_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x6a);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x6a;
 		break;
 	case COMBIOS_DYN_CLK_2_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x6c);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x6c;
 		break;
 	case COMBIOS_POWER_CONNECTOR_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x6e);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x6e;
 		break;
 	case COMBIOS_I2C_INFO_TABLE:
-		check_offset = RBIOS16(rdev->bios_header_start + 0x70);
-		if (check_offset)
-			offset = check_offset;
+		check_offset = 0x70;
 		break;
 		/* relative offset tables */
 	case COMBIOS_ASIC_INIT_3_TABLE:	/* offset from misc info */
@@ -439,11 +371,16 @@ static uint16_t combios_get_table_offset
 		}
 		break;
 	default:
+		check_offset = 0;
 		break;
 	}
 
-	return offset;
+	size = RBIOS8(rdev->bios_header_start + 0x6);
+	/* check absolute offset tables */
+	if (table < COMBIOS_ASIC_INIT_3_TABLE && check_offset && check_offset < size)
+		offset = RBIOS16(rdev->bios_header_start + check_offset);
 
+	return offset;
 }
 
 bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)


  parent reply	other threads:[~2013-07-31 13:32 UTC|newest]

Thread overview: 91+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-31 13:23 [00/84] 3.2.50-rc1 review Ben Hutchings
2013-07-31 13:23 ` [46/84] ALSA: usx2y: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [58/84] USB: storage: Add MicroVault Flash Drive to unusual_devs Ben Hutchings
2013-07-31 13:23 ` [60/84] USB: option: append Petatel NP10T device to GSM modems list Ben Hutchings
2013-07-31 13:23 ` [59/84] USB: misc: Add Manhattan Hi-Speed USB DVI Converter to sisusbvga Ben Hutchings
2013-07-31 13:23 ` [24/84] sparc64 address-congruence property Ben Hutchings
2013-07-31 13:23 ` [19/84] ifb: fix oops when loading the ifb failed Ben Hutchings
2013-07-31 13:23 ` [81/84] usb: serial: option: add Olivetti Olicard 200 Ben Hutchings
2013-07-31 13:23 ` [63/84] drm/radeon: Another card with wrong primary dac adj Ben Hutchings
2013-07-31 13:23 ` [22/84] vlan: fix a race in egress prio management Ben Hutchings
2013-07-31 13:23 ` [67/84] [SCSI] qla2xxx: Properly set the tagging for commands Ben Hutchings
2013-07-31 13:23 ` [80/84] usb: serial: option: blacklist ONDA MT689DC QMI interface Ben Hutchings
2013-07-31 13:23 ` [34/84] ASoC: sglt5000: Fix the default value of CHIP_SSS_CTRL Ben Hutchings
2013-07-31 13:23 ` [61/84] usb: cp210x support SEL C662 Vendor/Device Ben Hutchings
2013-07-31 13:23 ` [27/84] virtio: support unlocked queue poll Ben Hutchings
2013-07-31 13:23 ` [82/84] usb: serial: option.c: remove ONDA MT825UP product ID fromdriver Ben Hutchings
2013-07-31 13:23 ` [57/84] usb: serial: cp210x: Add USB ID for Netgear Switches embedded serial adapter Ben Hutchings
2013-07-31 13:23 ` [69/84] nfsd: nfsd_open: when dentry_open returns an error do not propagate as struct file Ben Hutchings
2013-07-31 13:23 ` [14/84] sunvnet: vnet_port_remove must call unregister_netdev Ben Hutchings
2013-07-31 13:23 ` [09/84] net: Swap ver and type in pppoe_hdr Ben Hutchings
2013-07-31 13:23 ` [47/84] ALSA: pxa2xx: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [76/84] usb: serial: option: Add ONYX 3G device support Ben Hutchings
2013-07-31 13:23 ` [21/84] atl1e: unmap partially mapped skb on dma error and free skb Ben Hutchings
2013-07-31 13:23 ` [56/84] ALSA: usb-audio: 6fire: return correct XRUN indication Ben Hutchings
2013-07-31 13:23 ` [48/84] ASoC: s6000: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [13/84] ipv6: ip6_append_data_mtu did not care about pmtudisc and frag_size Ben Hutchings
2013-07-31 13:23 ` [18/84] dummy: fix oops when loading the dummy failed Ben Hutchings
2013-07-31 13:23 ` Ben Hutchings [this message]
2013-07-31 13:23 ` [25/84] sparc: tsb must be flushed before tlb Ben Hutchings
2013-07-31 13:23 ` [20/84] atl1e: fix dma mapping warnings Ben Hutchings
2013-07-31 13:23 ` [68/84] [SCSI] sd: fix crash when UA received on DIF enabled device Ben Hutchings
2013-07-31 13:23 ` [33/84] xen/blkback: Check for insane amounts of request on the ring (v6) Ben Hutchings
2013-07-31 13:23 ` [43/84] ALSA: 6fire: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [55/84] Btrfs: re-add root to dead root list if we stop dropping it Ben Hutchings
2013-07-31 13:23 ` [11/84] l2tp: add missing .owner to struct pppox_proto Ben Hutchings
2013-07-31 13:23 ` [06/84] sh_eth: fix unhandled RFE interrupt Ben Hutchings
2013-07-31 13:23 ` [31/84] tracing: Use current_uid() for critical time tracing Ben Hutchings
2013-07-31 13:23 ` [08/84] x25: Fix broken locking in ioctl error paths Ben Hutchings
2013-07-31 13:23 ` [28/84] virtio_net: fix race in RX VQ processing Ben Hutchings
2013-07-31 13:23 ` [23/84] sparc32: vm_area_struct access for old Sun SPARCs Ben Hutchings
2013-07-31 13:23 ` [62/84] USB: cp210x: add MMB and PI ZigBee USB Device Support Ben Hutchings
2013-07-31 13:23 ` [15/84] ifb: fix rcu_sched self-detected stalls Ben Hutchings
2013-07-31 13:23 ` [16/84] macvtap: correctly linearize skb when zerocopy is used Ben Hutchings
2013-07-31 13:23 ` [53/84] ACPI / video: ignore BIOS initial backlight value for Fujitsu E753 Ben Hutchings
2013-08-02 13:46   ` Luis Henriques
2013-08-02 14:24     ` Ben Hutchings
2013-07-31 13:23 ` [50/84] ALSA: hda - Add new GPU codec ID to snd-hda Ben Hutchings
2013-07-31 13:23 ` [12/84] ipv6: call udp_push_pending_frames when uncorking a socket with AF_INET pending data Ben Hutchings
2013-07-31 13:23 ` [17/84] 9p: fix off by one causing access violations and memory corruption Ben Hutchings
2013-07-31 13:23 ` [10/84] ipv6,mcast: always hold idev->lock before mca_lock Ben Hutchings
2013-07-31 13:23 ` [51/84] ALSA: hda - Add new GPU codec ID to snd-hda Ben Hutchings
2013-07-31 13:23 ` [75/84] USB: ti_usb_3410_5052: fix dynamic-id matching Ben Hutchings
2013-07-31 13:23 ` [78/84] usb: host: xhci: Enable XHCI_SPURIOUS_SUCCESS for all controllers with xhci 1.0 Ben Hutchings
2013-07-31 13:23 ` [77/84] xhci: Avoid NULL pointer deref when host dies Ben Hutchings
2013-07-31 13:23 ` [73/84] usb: option: add TP-LINK MA260 Ben Hutchings
2013-07-31 13:23 ` [52/84] ata: Fix DVD not dectected at some platform with Wellsburg PCH Ben Hutchings
2013-07-31 13:23 ` [49/84] staging: line6: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [30/84] fanotify: info leak in copy_event_to_user() Ben Hutchings
2013-07-31 13:23 ` [03/84] macvtap: fix recovery from gup errors Ben Hutchings
2013-07-31 13:23 ` [39/84] usb: dwc3: gadget: don't prevent gadget from being probed if we fail Ben Hutchings
2013-07-31 13:23 ` [07/84] neighbour: fix a race in neigh_destroy() Ben Hutchings
2013-07-31 13:23 ` [71/84] staging: comedi: COMEDI_CANCEL ioctl should wake up read/write Ben Hutchings
2013-07-31 13:23 ` [32/84] xen/io/ring.h: new macro to detect whether there are too many requests on the ring Ben Hutchings
2013-07-31 13:23 ` [38/84] ACPI / memhotplug: Fix a stale pointer in error path Ben Hutchings
2013-07-31 13:23 ` [37/84] ext4: don't allow ext4_free_blocks() to fail due to ENOMEM Ben Hutchings
2013-07-31 13:23 ` [36/84] lockd: protect nlm_blocked access in nlmsvc_retry_blocked Ben Hutchings
2013-07-31 13:23 ` [54/84] Btrfs: fix lock leak when resuming snapshot deletion Ben Hutchings
2013-07-31 13:23 ` [42/84] ALSA: atiixp: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [44/84] ASoC: max98088 - fix element type of the register cache Ben Hutchings
2013-07-31 13:23 ` [72/84] staging: comedi: fix a race between do_cmd_ioctl() and read/write Ben Hutchings
2013-07-31 13:23 ` [01/84] bridge: fix switched interval for MLD Query types Ben Hutchings
2013-07-31 13:23 ` [70/84] USB: option: add D-Link DWM-152/C1 and DWM-156/C1 Ben Hutchings
2013-07-31 13:23 ` [41/84] ALSA: asihpi: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [04/84] ipv6: ip6_sk_dst_check() must not assume ipv6 dst Ben Hutchings
2013-07-31 13:23 ` [79/84] xhci: fix null pointer dereference on ring_doorbell_for_active_rings Ben Hutchings
2013-07-31 13:23 ` [05/84] af_key: fix info leaks in notify messages Ben Hutchings
2013-07-31 13:23 ` [66/84] [SCSI] isci: Fix a race condition in the SSP task management path Ben Hutchings
2013-07-31 13:23 ` [74/84] powerpc/modules: Module CRC relocation fix causes perf issues Ben Hutchings
2013-07-31 13:23 ` [45/84] ALSA: ua101: Fix unlocked snd_pcm_stop() call Ben Hutchings
2013-07-31 13:23 ` [02/84] ipv6: don't call addrconf_dst_alloc again when enable lo Ben Hutchings
2013-07-31 13:23 ` [26/84] ARM: OMAP: RX-51: change probe order of touchscreen and panel SPI devices Ben Hutchings
2013-08-01  5:49   ` Tomi Valkeinen
2013-08-01  9:32     ` Ben Hutchings
2013-08-02 20:14       ` Ben Hutchings
2013-07-31 13:23 ` [64/84] drm/radeon: improve dac adjust heuristics for legacy pdac Ben Hutchings
2013-07-31 13:23 ` [29/84] [SCSI] Fix incorrect memset in bnx2fc_parse_fcp_rsp Ben Hutchings
2013-07-31 13:23 ` [83/84] USB: mos7840: fix memory leak in open Ben Hutchings
2013-07-31 13:23 ` [84/84] usb: Clear both buffers when clearing a control transfer TT buffer Ben Hutchings
2013-07-31 13:23 ` [40/84] usb: dwc3: fix wrong bit mask in dwc3_event_type Ben Hutchings
2013-07-31 13:23 ` [35/84] ASoC: sglt5000: Fix SGTL5000_PLL_FRAC_DIV_MASK Ben Hutchings
2013-08-01  9:30 ` [00/84] 3.2.50-rc1 review Ben Hutchings

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=lsq.1375276989.359885615@decadent.org.uk \
    --to=ben@decadent.org.uk \
    --cc=akpm@linux-foundation.org \
    --cc=alexander.deucher@amd.com \
    --cc=kettenis@openbsd.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®