Re: Possible bug in amd64-agp (agpgart module)
From: Ochal Christophe
Date: Sat Dec 31 2005 - 11:13:02 EST
Hi all,
Some more info regarding my uphill battle with my machine :)
Ochal Christophe wrote:
Hi all,
Sorry for the intrusion, but i think i've stumbled across a bug in the
linux kernel.
On an Asus KV8-S XE motherboard, the agpgart module is unable to
properly determine the AGP aperture size, regardless of bios options
(AGP 8x mode & AGP 4x mode), this *might* also be related to possible
hangs in X11 when using DRI.
Bug was seen on the following config:
Asus K8V-S XE motherboard, 512MB ram with AMD Sempron 3200 (Athlon64
core)
Witnessed with an ATI Radeon 9700 Pro card and with an Asus Radeon
9200 SE.
I'll try & test this config with some more gfx cards to see if the gfx
card has any influence on the detection, but i'm not sure i have any
nVidia cards available.
This phenomenon has been found in atleast the following kernel versions:
linux 2.6.12-r9
linux 2.6.14-r4
linux 2.6.14-r5
linux 2.6.14-r7
The reported aperture size is always 32M, more details can be
provided, just ask what you need to know.
Some more info, might be worthwhile for the people in the know:
Motherboard: Asus K8V-X SE
lspci:
00:00.0 Host bridge: VIA Technologies, Inc. K8T800Pro Host Bridge
00:00.1 Host bridge: VIA Technologies, Inc. K8T800Pro Host Bridge
00:00.2 Host bridge: VIA Technologies, Inc. K8T800Pro Host Bridge
00:00.3 Host bridge: VIA Technologies, Inc. K8T800Pro Host Bridge
00:00.4 Host bridge: VIA Technologies, Inc. K8T800Pro Host Bridge
00:00.7 Host bridge: VIA Technologies, Inc. K8T800Pro Host Bridge
00:01.0 PCI bridge: VIA Technologies, Inc. VT8237 PCI bridge
[K8T800/K8T890 South]
00:0f.0 RAID bus controller: VIA Technologies, Inc. VIA VT6420 SATA RAID
Controller (rev 80)
00:0f.1 IDE interface: VIA Technologies, Inc.
VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (rev 06)
00:10.0 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
Controller (rev 81)
00:10.1 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
Controller (rev 81)
00:10.2 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
Controller (rev 81)
00:10.3 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1
Controller (rev 81)
00:10.4 USB Controller: VIA Technologies, Inc. USB 2.0 (rev 86)
00:11.0 ISA bridge: VIA Technologies, Inc. VT8237 ISA bridge
[KT600/K8T800/K8T890 South]
00:11.5 Multimedia audio controller: VIA Technologies, Inc.
VT8233/A/8235/8237 AC97 Audio Controller (rev 60)
00:12.0 Ethernet controller: VIA Technologies, Inc. VT6102 [Rhine-II]
(rev 78)
00:18.0 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron]
HyperTransport Technology Configuration
00:18.1 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron]
Address Map
00:18.2 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron]
DRAM Controller
00:18.3 Host bridge: Advanced Micro Devices [AMD] K8 [Athlon64/Opteron]
Miscellaneous Control
01:00.0 VGA compatible controller: ATI Technologies Inc Radeon R300 ND
[Radeon 9700 Pro]
01:00.1 Display controller: ATI Technologies Inc Radeon R300 [Radeon
9700 Pro] (Secondary)
Distribution:
Gentoo with kernel: 2.6.13-gentoo-r5
Problem witnessed with multiple kernels (see prior post), regardless of
BIOS settings.
Test results of testgart.c:
localhost ochal # ./test
version: 0.101
bridge id: 0x2821106
agp_mode: 0x1f000a1b
aper_base: 0xe4000000
aper_size: 32
pg_total: 112384
pg_system: 112384
pg_used: 0
entry.key : 0
entry.key : 1
Allocated 8 megs of GART memory
MemoryBenchmark: 8 mb/s
MemoryBenchmark: 8 mb/s
MemoryBenchmark: 9 mb/s
Average speed: 8 mb/s
Testing data integrity (1st pass): failed on first pass!
Testing data integrity (2nd pass): failed on second pass!
dmesg:
Linux agpgart interface v0.101 (c) Dave Jones
fglrx: module license 'Proprietary. (C) 2002 - ATI Technologies,
Starnberg, GERMANY' taints kernel.
[fglrx] Maximum main memory to use for locked dma buffers: 430 MBytes.
ACPI: PCI Interrupt 0000:01:00.0[A] -> GSI 16 (level, low) -> IRQ 201
[fglrx] module loaded - fglrx 8.20.8 [Dec 6 2005] on minor 0
[fglrx] ACPI power management is initialized.
Fire GL agpgart support
fglrx_agp is probing for an AGP device
Device found = 1106
failed pci_module_init
Unloading fglrx_agp
firegl_agp_probe failed
[fglrx] Failed to load fglrx_agp module
[fglrx] Error code 256
[fglrx] Failed to load ATI module agpgart
[fglrx] Fallback to internal agpgart module
Fire GL built-in AGP-support
Based on agpgart interface v0.99 (c) Jeff Hartmann
agpgart: Maximum main memory to use for agp memory: 439M
agpgart: Unsupported Via chipset (device id: 0282), you might want to
try agp_try_unsupported=1.
agpgart: no supported devices found.
[fglrx] Initialization of built-in AGP-support failed (ret=-19).
[fglrx:firegl_unlock] *ERROR* Process 5366 using kernel context 0
scsi: unknown opcode 0xe9
scsi: unknown opcode 0xed
scsi: unknown opcode 0x01
scsi: unknown opcode 0xf5
hda: packet command error: status=0x51 { DriveReady SeekComplete Error }
hda: packet command error: error=0x54 { AbortedCommand
LastFailedSense=0x05 }
ide: failed opcode was: unknown
hda: packet command error: status=0x51 { DriveReady SeekComplete Error }
hda: packet command error: error=0x54 { AbortedCommand
LastFailedSense=0x05 }
ide: failed opcode was: unknown
agpgart: Detected AGP bridge 0
agpgart: AGP aperture is 32M @ 0xe4000000
agpgart: Found an AGP 3.0 compliant device at 0000:00:00.0.
agpgart: test tried to set rate=x12. Setting to AGP3 x8 mode.
agpgart: Putting AGP V3 device at 0000:00:00.0 into 8x mode
agpgart: Putting AGP V3 device at 0000:01:00.0 into 8x mode
agpgart: Found an AGP 3.0 compliant device at 0000:00:00.0.
agpgart: test tried to set rate=x12. Setting to AGP3 x8 mode.
agpgart: Putting AGP V3 device at 0000:00:00.0 into 8x mode
agpgart: Putting AGP V3 device at 0000:01:00.0 into 8x mode
The testgart.c code:
/*
*
* Test program for AGPGART module under Linux
*
* Copyright (C) 1999 Jeff Hartmann,
* Precision Insight, Inc., Xi Graphics, Inc.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <linux/types.h>
#include <linux/agpgart.h>
#include <asm/mtrr.h>
#include <errno.h>
unsigned char *gart;
int gartfd;
int mtrr;
int usec( void ) {
struct timeval tv;
struct timezone tz;
gettimeofday( &tv, &tz );
return (tv.tv_sec & 2047) * 1000000 + tv.tv_usec;
}
int MemoryBenchmark( void *buffer, int dwords ) {
int i;
int start, end;
int mb;
int *base;
base = (int *)buffer;
start = usec();
for ( i = 0 ; i < dwords ; i += 8 ) {
base[i] =
base[i+1] =
base[i+2] =
base[i+3] =
base[i+4] =
base[i+5] =
base[i+6] =
base[i+7] = 0x15151515; /* dmapad nops */
}
end = usec();
mb = ( (float)dwords / 0x40000 ) * 1000000 / (end - start);
printf("MemoryBenchmark: %i mb/s\n", mb );
return mb;
}
int insert_gart(int page, int size)
{
agp_allocate entry;
agp_bind bind;
entry.type = 0;
entry.pg_count = size;
#ifdef DEBUG
printf("Using AGPIOC_ALLOCATE\n");
#endif
if(ioctl(gartfd, AGPIOC_ALLOCATE, &entry) != 0)
{
perror("ioctl(AGPIOC_ALLOCATE)");
exit(1);
}
bind.key = entry.key;
bind.pg_start = page;
#ifdef DEBUG
printf("Using AGPIOC_BIND\n");
#endif
if(ioctl(gartfd, AGPIOC_BIND, &bind))
{
perror("ioctl(AGPIOC_BIND)");
exit(1);
}
printf("entry.key : %i\n", entry.key);
return(entry.key);
}
int unbind_gart(int key)
{
agp_unbind unbind;
unbind.key = key;
#ifdef DEBUG
printf("Using AGPIOC_UNBIND\n");
#endif
if(ioctl(gartfd, AGPIOC_UNBIND, &unbind) != 0)
{
perror("ioctl(AGPIOC_UNBIND)");
exit(1);
}
return(0);
}
int bind_gart(int key, int page)
{
agp_bind bind;
bind.key = key;
bind.pg_start = page;
#ifdef DEBUG
printf("Using AGPIOC_BIND\n");
#endif
if(ioctl(gartfd, AGPIOC_BIND, &bind) != 0)
{
perror("ioctl(AGPIOC_BIND)");
exit(1);
}
return(0);
}
int remove_gart(int key)
{
#ifdef DEBUG
printf("Using AGPIOC_DEALLOCATE\n");
#endif
if(ioctl(gartfd, AGPIOC_DEALLOCATE, key) != 0)
{
perror("ioctl(GARTIOCREMOVE)");
exit(1);
}
return(0);
}
void openmtrr(void)
{
if ((mtrr = open("/proc/mtrr", O_WRONLY, 0)) == -1)
{
if (errno == ENOENT) {
perror("/proc/mtrr not found: MTRR not enabled\n");
} else {
perror("Error opening /proc/mtrr:");
perror("MTRR not enabled\n");
exit(1);
}
return;
}
}
int CoverRangeWithMTRR( int base, int range, int type )
{
int count;
/* set it if we aren't just checking the number */
if ( type != -1 ) {
struct mtrr_sentry sentry;
sentry.base = base;
sentry.size = range;
sentry.type = type;
if ( ioctl(mtrr, MTRRIOC_ADD_ENTRY, &sentry) == -1 ) {
perror("mtrr");
exit(1);
}
}
}
int init_agp(void)
{
agp_info info;
agp_setup setup;
#ifdef DEBUG
printf("Using AGPIOC_ACQUIRE\n");
#endif
if(ioctl(gartfd, AGPIOC_ACQUIRE) != 0)
{
perror("ioctl(AGPIOC_ACQUIRE)");
exit(1);
}
#ifdef DEBUG
printf("Using AGPIOC_INFO\n");
#endif
if(ioctl(gartfd, AGPIOC_INFO, &info) != 0)
{
perror("ioctl(AGPIOC_INFO)");
exit(1);
}
printf("version: %i.%i\n", info.version.major, info.version.minor);
printf("bridge id: 0x%lx\n", info.bridge_id);
printf("agp_mode: 0x%lx\n", info.agp_mode);
printf("aper_base: 0x%lx\n", info.aper_base);
printf("aper_size: %i\n", info.aper_size);
printf("pg_total: %i\n", info.pg_total);
printf("pg_system: %i\n", info.pg_system);
printf("pg_used: %i\n", info.pg_used);
openmtrr();
if (mtrr != -1) {
CoverRangeWithMTRR(info.aper_base, info.aper_size * 0x100000,
MTRR_TYPE_WRCOMB);
}
gart = mmap(NULL, info.aper_size * 0x100000, PROT_READ | PROT_WRITE, MAP_SHARED, gartfd, 0);
if(gart == (unsigned char *) 0xffffffff)
{
perror("mmap");
close(gartfd);
exit(1);
}
setup.agp_mode = info.agp_mode;
#ifdef DEBUG
printf("Using AGPIOC_SETUP\n");
#endif
if(ioctl(gartfd, AGPIOC_SETUP, &setup) != 0)
{
perror("ioctl(AGPIOC_SETUP)");
exit(1);
}
return(0);
}
int xchangeDummy;
void FlushWriteCombining( void ) {
__asm__ volatile( " push %%eax ; xchg %%eax, %0 ; pop %%eax" : : "m" (xchangeDummy));
__asm__ volatile( " push %%eax ; push %%ebx ; push %%ecx ; push %%edx ; movl $0,%%eax ; cpuid ; pop %%edx ; pop %%ecx ; pop %%ebx ; pop %%eax" : /* no outputs */ : /* no inputs */ );
}
void BenchMark()
{
int i, worked = 1;
i = MemoryBenchmark(gart, (1024 * 1024 * 4) / 4) +
MemoryBenchmark(gart, (1024 * 1024 * 4) / 4) +
MemoryBenchmark(gart, (1024 * 1024 * 4) / 4);
printf("Average speed: %i mb/s\n", i /3);
printf("Testing data integrity (1st pass): ");
fflush(stdout);
FlushWriteCombining();
for (i=0; i < 8 * 0x100000; i++)
{
gart[i] = i % 256;
}
FlushWriteCombining();
for (i=0; i < 8 * 0x100000; i++)
{
if(!(gart[i] == i % 256))
{
#ifdef DEBUG
printf("failed on %i, gart[i] = %i\n", i, gart[i]);
#endif
worked = 0;
}
}
if (!worked)
printf("failed on first pass!\n");
else
printf("passed on first pass.\n");
unbind_gart(0);
unbind_gart(1);
bind_gart(0, 0);
bind_gart(1, 1024);
worked = 1;
printf("Testing data integrity (2nd pass): ");
fflush(stdout);
for (i=0; i < 8 * 0x100000; i++)
{
if(!(gart[i] == i % 256))
{
#ifdef DEBUG
printf("failed on %i, gart[i] = %i\n", i, gart[i]);
#endif
worked = 0;
}
}
if (!worked)
printf("failed on second pass!\n");
else
printf("passed on second pass.\n");
}
int main()
{
int i;
int key;
int key2;
agp_info info;
gartfd = open("/dev/agpgart", O_RDWR);
if (gartfd == -1)
{
perror("open");
exit(1);
}
init_agp();
key = insert_gart(0, 1024);
key2 = insert_gart(1024, 1024);
#ifdef DEBUG
printf("Using AGPIOC_INFO\n");
if(ioctl(gartfd, AGPIOC_INFO, &info) != 0)
{
perror("ioctl(AGPIOC_INFO)");
exit(1);
}
printf("version: %i.%i\n", info.version.major, info.version.minor);
printf("bridge id: 0x%lx\n", info.bridge_id);
printf("agp_mode: 0x%lx\n", info.agp_mode);
printf("aper_base: 0x%lx\n", info.aper_base);
printf("aper_size: %i\n", info.aper_size);
printf("pg_total: %i\n", info.pg_total);
printf("pg_system: %i\n", info.pg_system);
printf("pg_used: %i\n", info.pg_used);
#endif
printf("Allocated 8 megs of GART memory\n");
BenchMark();
remove_gart(key);
remove_gart(key2);
#ifdef DEBUG
printf("Using AGPIOC_RELEASE\n");
#endif
if(ioctl(gartfd, AGPIOC_RELEASE) != 0)
{
perror("ioctl(AGPIOC_RELEASE)");
exit(1);
}
close(gartfd);
}
I don't know how correct this test program is, i'm willing to test the
hell out of this.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/