From 55057660f035a03078910d678e5fd9b0cb0b795a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 6 Sep 2006 23:25:14 -0700 Subject: Put the PCI device/vendor id in the drm_device_t. This helps us unbreak FreeBSD DRM from the 965 changes. --- shared-core/i915_dma.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index ba8c56ee..3863490c 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -31,10 +31,10 @@ #include "i915_drm.h" #include "i915_drv.h" -#define IS_I965G(dev) (dev->pdev->device == 0x2972 || \ - dev->pdev->device == 0x2982 || \ - dev->pdev->device == 0x2992 || \ - dev->pdev->device == 0x29A2) +#define IS_I965G(dev) (dev->pci_device == 0x2972 || \ + dev->pci_device == 0x2982 || \ + dev->pci_device == 0x2992 || \ + dev->pci_device == 0x29A2) /* Really want an OS-independent resettable timer. Would like to have -- cgit v1.2.3 From 3cc64a943a7240c73c92ab103ba0502b9ec07fee Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 12 Sep 2006 06:13:14 +1000 Subject: drm: use radeon specific names for radeon flags --- shared-core/drm_pciids.txt | 176 ++++++++++++++++++++++----------------------- shared-core/radeon_cp.c | 46 ++++++------ shared-core/radeon_drv.h | 20 +++--- shared-core/radeon_state.c | 10 +-- 4 files changed, 126 insertions(+), 126 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index 9ef2c001..9e0c0992 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -1,11 +1,11 @@ [radeon] -0x1002 0x3150 CHIP_RV380|CHIP_IS_MOBILITY "ATI Radeon Mobility X600 M24" -0x1002 0x3152 CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Radeon Mobility X300 M24" -0x1002 0x3154 CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI FireGL M24 GL" -0x1002 0x3E50 CHIP_RV380|CHIP_NEW_MEMMAP "ATI Radeon RV380 X600" -0x1002 0x3E54 CHIP_RV380|CHIP_NEW_MEMMAP "ATI FireGL V3200 RV380" -0x1002 0x4136 CHIP_RS100|CHIP_IS_IGP "ATI Radeon RS100 IGP 320" -0x1002 0x4137 CHIP_RS200|CHIP_IS_IGP "ATI Radeon RS200 IGP 340" +0x1002 0x3150 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X600 M24" +0x1002 0x3152 CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X300 M24" +0x1002 0x3154 CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI FireGL M24 GL" +0x1002 0x3E50 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV380 X600" +0x1002 0x3E54 CHIP_RV380|RADEON_NEW_MEMMAP "ATI FireGL V3200 RV380" +0x1002 0x4136 CHIP_RS100|RADEON_IS_IGP "ATI Radeon RS100 IGP 320" +0x1002 0x4137 CHIP_RS200|RADEON_IS_IGP "ATI Radeon RS200 IGP 340" 0x1002 0x4144 CHIP_R300 "ATI Radeon AD 9500" 0x1002 0x4145 CHIP_R300 "ATI Radeon AE 9700 Pro" 0x1002 0x4146 CHIP_R300 "ATI Radeon AF R300 9600TX" @@ -21,35 +21,35 @@ 0x1002 0x4154 CHIP_RV350 "ATI FireGL AT T2" 0x1002 0x4155 CHIP_RV350 "ATI Radeon 9650" 0x1002 0x4156 CHIP_RV350 "ATI FireGL AV RV360 T2" -0x1002 0x4237 CHIP_RS200|CHIP_IS_IGP "ATI Radeon RS250 IGP" +0x1002 0x4237 CHIP_RS200|RADEON_IS_IGP "ATI Radeon RS250 IGP" 0x1002 0x4242 CHIP_R200 "ATI Radeon BB R200 AIW 8500DV" 0x1002 0x4243 CHIP_R200 "ATI Radeon BC R200" -0x1002 0x4336 CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY "ATI Radeon RS100 Mobility U1" -0x1002 0x4337 CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY "ATI Radeon RS200 Mobility IGP 340M" -0x1002 0x4437 CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY "ATI Radeon RS250 Mobility IGP" +0x1002 0x4336 CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS100 Mobility U1" +0x1002 0x4337 CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS200 Mobility IGP 340M" +0x1002 0x4437 CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS250 Mobility IGP" 0x1002 0x4966 CHIP_RV250 "ATI Radeon If RV250 9000" 0x1002 0x4967 CHIP_RV250 "ATI Radeon Ig RV250 9000" -0x1002 0x4A48 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JH R420 X800" -0x1002 0x4A49 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JI R420 X800 Pro" -0x1002 0x4A4A CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JJ R420 X800 SE" -0x1002 0x4A4B CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JK R420 X800 XT" -0x1002 0x4A4C CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JL R420 X800" -0x1002 0x4A4D CHIP_R420|CHIP_NEW_MEMMAP "ATI FireGL JM X3-256" -0x1002 0x4A4E CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Radeon JN R420 Mobility M18" -0x1002 0x4A4F CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JO R420 X800 SE" -0x1002 0x4A50 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JP R420 X800 XT PE" -0x1002 0x4A54 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon JT R420 AIW X800 VE" -0x1002 0x4B49 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R481 X850 XT" -0x1002 0x4B4A CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R481 X850 SE" -0x1002 0x4B4B CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R481 X850 Pro" -0x1002 0x4B4C CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R481 X850 XT PE" -0x1002 0x4C57 CHIP_RV200|CHIP_IS_MOBILITY "ATI Radeon LW RV200 Mobility 7500 M7" -0x1002 0x4C58 CHIP_RV200|CHIP_IS_MOBILITY "ATI Radeon LX RV200 Mobility FireGL 7800 M7" -0x1002 0x4C59 CHIP_RV100|CHIP_IS_MOBILITY "ATI Radeon LY RV100 Mobility M6" -0x1002 0x4C5A CHIP_RV100|CHIP_IS_MOBILITY "ATI Radeon LZ RV100 Mobility M6" -0x1002 0x4C64 CHIP_RV250|CHIP_IS_MOBILITY "ATI Radeon Ld RV250 Mobility 9000 M9" +0x1002 0x4A48 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JH R420 X800" +0x1002 0x4A49 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JI R420 X800 Pro" +0x1002 0x4A4A CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JJ R420 X800 SE" +0x1002 0x4A4B CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JK R420 X800 XT" +0x1002 0x4A4C CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JL R420 X800" +0x1002 0x4A4D CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL JM X3-256" +0x1002 0x4A4E CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon JN R420 Mobility M18" +0x1002 0x4A4F CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JO R420 X800 SE" +0x1002 0x4A50 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JP R420 X800 XT PE" +0x1002 0x4A54 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon JT R420 AIW X800 VE" +0x1002 0x4B49 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 XT" +0x1002 0x4B4A CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 SE" +0x1002 0x4B4B CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 Pro" +0x1002 0x4B4C CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R481 X850 XT PE" +0x1002 0x4C57 CHIP_RV200|RADEON_IS_MOBILITY "ATI Radeon LW RV200 Mobility 7500 M7" +0x1002 0x4C58 CHIP_RV200|RADEON_IS_MOBILITY "ATI Radeon LX RV200 Mobility FireGL 7800 M7" +0x1002 0x4C59 CHIP_RV100|RADEON_IS_MOBILITY "ATI Radeon LY RV100 Mobility M6" +0x1002 0x4C5A CHIP_RV100|RADEON_IS_MOBILITY "ATI Radeon LZ RV100 Mobility M6" +0x1002 0x4C64 CHIP_RV250|RADEON_IS_MOBILITY "ATI Radeon Ld RV250 Mobility 9000 M9" 0x1002 0x4C66 CHIP_RV250 "ATI Radeon Lf RV250 Mobility 9000 M9 / FireMV 2400 PCI" -0x1002 0x4C67 CHIP_RV250|CHIP_IS_MOBILITY "ATI Radeon Lg RV250 Mobility 9000 M9" +0x1002 0x4C67 CHIP_RV250|RADEON_IS_MOBILITY "ATI Radeon Lg RV250 Mobility 9000 M9" 0x1002 0x4E44 CHIP_R300 "ATI Radeon ND R300 9700 Pro" 0x1002 0x4E45 CHIP_R300 "ATI Radeon NE R300 9500 Pro / 9700" 0x1002 0x4E46 CHIP_R300 "ATI Radeon NF R300 9600TX" @@ -58,16 +58,16 @@ 0x1002 0x4E49 CHIP_R350 "ATI Radeon NI R350 9800" 0x1002 0x4E4A CHIP_R350 "ATI Radeon NJ R360 9800 XT" 0x1002 0x4E4B CHIP_R350 "ATI FireGL NK X2" -0x1002 0x4E50 CHIP_RV350|CHIP_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NP" -0x1002 0x4E51 CHIP_RV350|CHIP_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NQ" -0x1002 0x4E52 CHIP_RV350|CHIP_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M11 NR" -0x1002 0x4E53 CHIP_RV350|CHIP_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NS" -0x1002 0x4E54 CHIP_RV350|CHIP_IS_MOBILITY "ATI FireGL T2/T2e" -0x1002 0x4E56 CHIP_RV350|CHIP_IS_MOBILITY "ATI Radeon Mobility 9550" -0x1002 0x5144 CHIP_R100|CHIP_SINGLE_CRTC "ATI Radeon QD R100" -0x1002 0x5145 CHIP_R100|CHIP_SINGLE_CRTC "ATI Radeon QE R100" -0x1002 0x5146 CHIP_R100|CHIP_SINGLE_CRTC "ATI Radeon QF R100" -0x1002 0x5147 CHIP_R100|CHIP_SINGLE_CRTC "ATI Radeon QG R100" +0x1002 0x4E50 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NP" +0x1002 0x4E51 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NQ" +0x1002 0x4E52 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M11 NR" +0x1002 0x4E53 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon RV350 Mobility 9600 M10 NS" +0x1002 0x4E54 CHIP_RV350|RADEON_IS_MOBILITY "ATI FireGL T2/T2e" +0x1002 0x4E56 CHIP_RV350|RADEON_IS_MOBILITY "ATI Radeon Mobility 9550" +0x1002 0x5144 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QD R100" +0x1002 0x5145 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QE R100" +0x1002 0x5146 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QF R100" +0x1002 0x5147 CHIP_R100|RADEON_SINGLE_CRTC "ATI Radeon QG R100" 0x1002 0x5148 CHIP_R200 "ATI Radeon QH R200 8500" 0x1002 0x514C CHIP_R200 "ATI Radeon QL R200 8500 LE" 0x1002 0x514D CHIP_R200 "ATI Radeon QM R200 9100" @@ -76,59 +76,59 @@ 0x1002 0x5159 CHIP_RV100 "ATI Radeon QY RV100 7000/VE" 0x1002 0x515A CHIP_RV100 "ATI Radeon QZ RV100 7000/VE" 0x1002 0x515E CHIP_RV100 "ATI ES1000 RN50" -0x1002 0x5460 CHIP_RV380|CHIP_IS_MOBILITY "ATI Radeon Mobility X300 M22" -0x1002 0x5462 CHIP_RV380|CHIP_IS_MOBILITY "ATI Radeon Mobility X600 SE M24C" -0x1002 0x5464 CHIP_RV380|CHIP_IS_MOBILITY "ATI FireGL M22 GL 5464" -0x1002 0x5548 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R423 X800" -0x1002 0x5549 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R423 X800 Pro" -0x1002 0x554A CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R423 X800 XT PE" -0x1002 0x554B CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R423 X800 SE" -0x1002 0x554C CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R430 X800 XTP" -0x1002 0x554D CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R430 X800 XL" -0x1002 0x554E CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R430 X800 SE" -0x1002 0x554F CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R430 X800" -0x1002 0x5550 CHIP_R420|CHIP_NEW_MEMMAP "ATI FireGL V7100 R423" -0x1002 0x5551 CHIP_R420|CHIP_NEW_MEMMAP "ATI FireGL V5100 R423 UQ" -0x1002 0x5552 CHIP_R420|CHIP_NEW_MEMMAP "ATI FireGL unknown R423 UR" -0x1002 0x5554 CHIP_R420|CHIP_NEW_MEMMAP "ATI FireGL unknown R423 UT" -0x1002 0x564A CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Mobility FireGL V5000 M26" -0x1002 0x564B CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Mobility FireGL V5000 M26" -0x1002 0x564F CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Radeon Mobility X700 XL M26" -0x1002 0x5652 CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Radeon Mobility X700 M26" -0x1002 0x5653 CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Radeon Mobility X700 M26" -0x1002 0x5834 CHIP_RS300|CHIP_IS_IGP "ATI Radeon RS300 9100 IGP" -0x1002 0x5835 CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY "ATI Radeon RS300 Mobility IGP" +0x1002 0x5460 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X300 M22" +0x1002 0x5462 CHIP_RV380|RADEON_IS_MOBILITY "ATI Radeon Mobility X600 SE M24C" +0x1002 0x5464 CHIP_RV380|RADEON_IS_MOBILITY "ATI FireGL M22 GL 5464" +0x1002 0x5548 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800" +0x1002 0x5549 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 Pro" +0x1002 0x554A CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 XT PE" +0x1002 0x554B CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 SE" +0x1002 0x554C CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800 XTP" +0x1002 0x554D CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800 XL" +0x1002 0x554E CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800 SE" +0x1002 0x554F CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R430 X800" +0x1002 0x5550 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL V7100 R423" +0x1002 0x5551 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL V5100 R423 UQ" +0x1002 0x5552 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL unknown R423 UR" +0x1002 0x5554 CHIP_R420|RADEON_NEW_MEMMAP "ATI FireGL unknown R423 UT" +0x1002 0x564A CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5000 M26" +0x1002 0x564B CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5000 M26" +0x1002 0x564F CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 XL M26" +0x1002 0x5652 CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 M26" +0x1002 0x5653 CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon Mobility X700 M26" +0x1002 0x5834 CHIP_RS300|RADEON_IS_IGP "ATI Radeon RS300 9100 IGP" +0x1002 0x5835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY "ATI Radeon RS300 Mobility IGP" 0x1002 0x5960 CHIP_RV280 "ATI Radeon RV280 9250" 0x1002 0x5961 CHIP_RV280 "ATI Radeon RV280 9200" 0x1002 0x5962 CHIP_RV280 "ATI Radeon RV280 9200" 0x1002 0x5964 CHIP_RV280 "ATI Radeon RV280 9200 SE" 0x1002 0x5965 CHIP_RV280 "ATI FireMV 2200 PCI" 0x1002 0x5969 CHIP_RV100 "ATI ES1000 RN50" -0x1002 0x5b60 CHIP_RV380|CHIP_NEW_MEMMAP "ATI Radeon RV370 X300 SE" -0x1002 0x5b62 CHIP_RV380|CHIP_NEW_MEMMAP "ATI Radeon RV370 X600 Pro" -0x1002 0x5b63 CHIP_RV380|CHIP_NEW_MEMMAP "ATI Radeon RV370 X550" -0x1002 0x5b64 CHIP_RV380|CHIP_NEW_MEMMAP "ATI FireGL V3100 (RV370) 5B64" -0x1002 0x5b65 CHIP_RV380|CHIP_NEW_MEMMAP "ATI FireMV 2200 PCIE (RV370) 5B65" -0x1002 0x5c61 CHIP_RV280|CHIP_IS_MOBILITY "ATI Radeon RV280 Mobility" -0x1002 0x5c63 CHIP_RV280|CHIP_IS_MOBILITY "ATI Radeon RV280 Mobility" -0x1002 0x5d48 CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Mobility Radeon X800 XT M28" -0x1002 0x5d49 CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Mobility FireGL V5100 M28" -0x1002 0x5d4a CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Mobility Radeon X800 M28" -0x1002 0x5d4c CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R480 X850" -0x1002 0x5d4d CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R480 X850 XT PE" -0x1002 0x5d4e CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R480 X850 SE" -0x1002 0x5d4f CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R480 X850 Pro" -0x1002 0x5d50 CHIP_R420|CHIP_NEW_MEMMAP "ATI unknown Radeon / FireGL R480" -0x1002 0x5d52 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R480 X850 XT" -0x1002 0x5d57 CHIP_R420|CHIP_NEW_MEMMAP "ATI Radeon R423 X800 XT" -0x1002 0x5e48 CHIP_RV410|CHIP_NEW_MEMMAP "ATI FireGL V5000 RV410" -0x1002 0x5e4a CHIP_RV410|CHIP_NEW_MEMMAP "ATI Radeon RV410 X700 XT" -0x1002 0x5e4b CHIP_RV410|CHIP_NEW_MEMMAP "ATI Radeon RV410 X700 Pro" -0x1002 0x5e4c CHIP_RV410|CHIP_NEW_MEMMAP "ATI Radeon RV410 X700 SE" -0x1002 0x5e4d CHIP_RV410|CHIP_NEW_MEMMAP "ATI Radeon RV410 X700" -0x1002 0x5e4f CHIP_RV410|CHIP_NEW_MEMMAP "ATI Radeon RV410 X700 SE" -0x1002 0x7834 CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP "ATI Radeon RS350 9000/9100 IGP" -0x1002 0x7835 CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP "ATI Radeon RS350 Mobility IGP" +0x1002 0x5b60 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X300 SE" +0x1002 0x5b62 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X600 Pro" +0x1002 0x5b63 CHIP_RV380|RADEON_NEW_MEMMAP "ATI Radeon RV370 X550" +0x1002 0x5b64 CHIP_RV380|RADEON_NEW_MEMMAP "ATI FireGL V3100 (RV370) 5B64" +0x1002 0x5b65 CHIP_RV380|RADEON_NEW_MEMMAP "ATI FireMV 2200 PCIE (RV370) 5B65" +0x1002 0x5c61 CHIP_RV280|RADEON_IS_MOBILITY "ATI Radeon RV280 Mobility" +0x1002 0x5c63 CHIP_RV280|RADEON_IS_MOBILITY "ATI Radeon RV280 Mobility" +0x1002 0x5d48 CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X800 XT M28" +0x1002 0x5d49 CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility FireGL V5100 M28" +0x1002 0x5d4a CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Mobility Radeon X800 M28" +0x1002 0x5d4c CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850" +0x1002 0x5d4d CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 XT PE" +0x1002 0x5d4e CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 SE" +0x1002 0x5d4f CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 Pro" +0x1002 0x5d50 CHIP_R420|RADEON_NEW_MEMMAP "ATI unknown Radeon / FireGL R480" +0x1002 0x5d52 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R480 X850 XT" +0x1002 0x5d57 CHIP_R420|RADEON_NEW_MEMMAP "ATI Radeon R423 X800 XT" +0x1002 0x5e48 CHIP_RV410|RADEON_NEW_MEMMAP "ATI FireGL V5000 RV410" +0x1002 0x5e4a CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 XT" +0x1002 0x5e4b CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 Pro" +0x1002 0x5e4c CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE" +0x1002 0x5e4d CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700" +0x1002 0x5e4f CHIP_RV410|RADEON_NEW_MEMMAP "ATI Radeon RV410 X700 SE" +0x1002 0x7834 CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP "ATI Radeon RS350 9000/9100 IGP" +0x1002 0x7835 CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP "ATI Radeon RS350 Mobility IGP" [r128] 0x1002 0x4c45 0 "ATI Rage 128 Mobility LE (PCI)" diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index 4e7b2823..4135f4d5 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1130,7 +1130,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | (dev_priv->fb_location >> 16)); #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) { + if (dev_priv->flags & RADEON_IS_AGP) { RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + @@ -1158,7 +1158,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, dev_priv->ring.tail = cur_read_ptr; #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) { + if (dev_priv->flags & RADEON_IS_AGP) { RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base + dev_priv->gart_vm_start); @@ -1301,7 +1301,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) { u32 tmp; - if (dev_priv->flags & CHIP_IS_PCIE) { + if (dev_priv->flags & RADEON_IS_PCIE) { radeon_set_pciegart(dev_priv, on); return; } @@ -1339,26 +1339,26 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) DRM_DEBUG("\n"); /* if we require new memory map but we don't have it fail */ - if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap) + if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); } - if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) + if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { DRM_DEBUG("Forcing AGP card to PCI mode\n"); - dev_priv->flags &= ~CHIP_IS_AGP; + dev_priv->flags &= ~RADEON_IS_AGP; } - else if (!(dev_priv->flags & (CHIP_IS_AGP | CHIP_IS_PCI | CHIP_IS_PCIE)) + else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) && !init->is_pci) { DRM_DEBUG("Restoring AGP flag\n"); - dev_priv->flags |= CHIP_IS_AGP; + dev_priv->flags |= RADEON_IS_AGP; } - if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) { + if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { DRM_ERROR("PCI GART memory not allocated!\n"); radeon_do_cleanup_cp(dev); return DRM_ERR(EINVAL); @@ -1501,7 +1501,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) init->sarea_priv_offset); #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) { + if (dev_priv->flags & RADEON_IS_AGP) { drm_core_ioremap(dev_priv->cp_ring, dev); drm_core_ioremap(dev_priv->ring_rptr, dev); drm_core_ioremap(dev->agp_buffer_map, dev); @@ -1560,7 +1560,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) * align it down. */ #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) { + if (dev_priv->flags & RADEON_IS_AGP) { base = dev->agp->base; /* Check if valid */ if ((base + dev_priv->gart_size) > dev_priv->fb_location && @@ -1590,7 +1590,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) } #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) + if (dev_priv->flags & RADEON_IS_AGP) dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - dev->agp->base + dev_priv->gart_vm_start); @@ -1616,7 +1616,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) { + if (dev_priv->flags & RADEON_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart(dev_priv, 0); } else @@ -1636,7 +1636,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->gart_info.mapping.handle; dev_priv->gart_info.is_pcie = - !!(dev_priv->flags & CHIP_IS_PCIE); + !!(dev_priv->flags & RADEON_IS_PCIE); dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB; @@ -1648,7 +1648,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) DRM_ATI_GART_MAIN; dev_priv->gart_info.addr = NULL; dev_priv->gart_info.bus_addr = 0; - if (dev_priv->flags & CHIP_IS_PCIE) { + if (dev_priv->flags & RADEON_IS_PCIE) { DRM_ERROR ("Cannot use PCI Express without GART in FB memory\n"); radeon_do_cleanup_cp(dev); @@ -1690,7 +1690,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) drm_irq_uninstall(dev); #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) { + if (dev_priv->flags & RADEON_IS_AGP) { if (dev_priv->cp_ring != NULL) { drm_core_ioremapfree(dev_priv->cp_ring, dev); dev_priv->cp_ring = NULL; @@ -1745,7 +1745,7 @@ static int radeon_do_resume_cp(drm_device_t * dev) DRM_DEBUG("Starting radeon_do_resume_cp()\n"); #if __OS_HAS_AGP - if (dev_priv->flags & CHIP_IS_AGP) { + if (dev_priv->flags & RADEON_IS_AGP) { /* Turn off PCI GART */ radeon_set_pcigart(dev_priv, 0); } else @@ -2194,7 +2194,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) dev->dev_private = (void *)dev_priv; dev_priv->flags = flags; - switch (flags & CHIP_FAMILY_MASK) { + switch (flags & RADEON_FAMILY_MASK) { case CHIP_R100: case CHIP_RV200: case CHIP_R200: @@ -2202,7 +2202,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) case CHIP_R350: case CHIP_R420: case CHIP_RV410: - dev_priv->flags |= CHIP_HAS_HIERZ; + dev_priv->flags |= RADEON_HAS_HIERZ; break; default: /* all other chips have no hierarchical z buffer */ @@ -2210,14 +2210,14 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) } if (drm_device_is_agp(dev)) - dev_priv->flags |= CHIP_IS_AGP; + dev_priv->flags |= RADEON_IS_AGP; else if (drm_device_is_pcie(dev)) - dev_priv->flags |= CHIP_IS_PCIE; + dev_priv->flags |= RADEON_IS_PCIE; else - dev_priv->flags |= CHIP_IS_PCI; + dev_priv->flags |= RADEON_IS_PCI; DRM_DEBUG("%s card detected\n", - ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI")))); + ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); return ret; } diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 5fa8254a..5fc93310 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -134,16 +134,16 @@ enum radeon_cp_microcode_version { * Chip flags */ enum radeon_chip_flags { - CHIP_FAMILY_MASK = 0x0000ffffUL, - CHIP_FLAGS_MASK = 0xffff0000UL, - CHIP_IS_MOBILITY = 0x00010000UL, - CHIP_IS_IGP = 0x00020000UL, - CHIP_SINGLE_CRTC = 0x00040000UL, - CHIP_IS_AGP = 0x00080000UL, - CHIP_HAS_HIERZ = 0x00100000UL, - CHIP_IS_PCIE = 0x00200000UL, - CHIP_NEW_MEMMAP = 0x00400000UL, - CHIP_IS_PCI = 0x00800000UL, + RADEON_FAMILY_MASK = 0x0000ffffUL, + RADEON_FLAGS_MASK = 0xffff0000UL, + RADEON_IS_MOBILITY = 0x00010000UL, + RADEON_IS_IGP = 0x00020000UL, + RADEON_SINGLE_CRTC = 0x00040000UL, + RADEON_IS_AGP = 0x00080000UL, + RADEON_HAS_HIERZ = 0x00100000UL, + RADEON_IS_PCIE = 0x00200000UL, + RADEON_NEW_MEMMAP = 0x00400000UL, + RADEON_IS_PCI = 0x00800000UL, }; #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 8c1a4065..0a196c06 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, */ dev_priv->sarea_priv->ctx_owner = 0; - if ((dev_priv->flags & CHIP_HAS_HIERZ) + if ((dev_priv->flags & RADEON_HAS_HIERZ) && (flags & RADEON_USE_HIERZ)) { /* FIXME : reverse engineer that for Rx00 cards */ /* FIXME : the mask supposedly contains low-res z values. So can't set @@ -906,7 +906,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, for (i = 0; i < nbox; i++) { int tileoffset, nrtilesx, nrtilesy, j; /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ - if ((dev_priv->flags & CHIP_HAS_HIERZ) + if ((dev_priv->flags & RADEON_HAS_HIERZ) && !(dev_priv->microcode_version == UCODE_R200)) { /* FIXME : figure this out for r200 (when hierz is enabled). Or maybe r200 actually doesn't need to put the low-res z value into @@ -990,7 +990,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, } /* TODO don't always clear all hi-level z tiles */ - if ((dev_priv->flags & CHIP_HAS_HIERZ) + if ((dev_priv->flags & RADEON_HAS_HIERZ) && (dev_priv->microcode_version == UCODE_R200) && (flags & RADEON_USE_HIERZ)) /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ @@ -3031,9 +3031,9 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) break; case RADEON_PARAM_CARD_TYPE: - if (dev_priv->flags & CHIP_IS_PCIE) + if (dev_priv->flags & RADEON_IS_PCIE) value = RADEON_CARD_PCIE; - else if (dev_priv->flags & CHIP_IS_AGP) + else if (dev_priv->flags & RADEON_IS_AGP) value = RADEON_CARD_AGP; else value = RADEON_CARD_PCI; -- cgit v1.2.3 From 6ba9127753eff7615ba553fbc567aec98ecf8104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 15 Sep 2006 16:37:47 +0200 Subject: Use register writes instead of BITBLT_MULTI packets for buffer swap blits. This takes up two more ring buffer entries per rectangle blitted but makes sure the blit is performed top to bottom, reducing the likelyhood of tearing. --- shared-core/radeon_drv.h | 3 +++ shared-core/radeon_state.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 5fc93310..6ea2a175 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -423,6 +423,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp, #define RADEON_RB3D_COLOROFFSET 0x1c40 #define RADEON_RB3D_COLORPITCH 0x1c48 +#define RADEON_SRC_X_Y 0x1590 + #define RADEON_DP_GUI_MASTER_CNTL 0x146c # define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) # define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) @@ -440,6 +442,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp, # define RADEON_ROP3_S 0x00cc0000 # define RADEON_ROP3_P 0x00f00000 #define RADEON_DP_WRITE_MASK 0x16cc +#define RADEON_SRC_PITCH_OFFSET 0x1428 #define RADEON_DST_PITCH_OFFSET 0x142c #define RADEON_DST_PITCH_OFFSET_C 0x1c80 # define RADEON_DST_TILE_LINEAR (0 << 30) diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 0a196c06..5b1ca539 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -1262,9 +1262,9 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); - BEGIN_RING(7); + BEGIN_RING(9); - OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); + OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0)); OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_NONE | @@ -1276,6 +1276,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) /* Make this work even if front & back are flipped: */ + OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); if (dev_priv->current_page == 0) { OUT_RING(dev_priv->back_pitch_offset); OUT_RING(dev_priv->front_pitch_offset); @@ -1284,6 +1285,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) OUT_RING(dev_priv->back_pitch_offset); } + OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2)); OUT_RING((x << 16) | y); OUT_RING((x << 16) | y); OUT_RING((w << 16) | h); -- cgit v1.2.3 From 1f71b8d7a456fe3ec4bfc2fed70b7420cdd0d55a Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Wed, 20 Sep 2006 19:44:57 +0200 Subject: do a TCL state flush before accessing VAP_CNTL to prevent lockups on r200 when enabling/disabling vertex programs --- shared-core/radeon_state.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 5b1ca539..b4478019 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -174,6 +174,14 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * } break; + case R200_EMIT_VAP_CTL: { + RING_LOCALS; + BEGIN_RING(2); + OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); + ADVANCE_RING(); + } + break; + case RADEON_EMIT_RB3D_COLORPITCH: case RADEON_EMIT_RE_LINE_PATTERN: case RADEON_EMIT_SE_LINE_WIDTH: @@ -201,7 +209,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: case R200_EMIT_TFACTOR_0: case R200_EMIT_VTX_FMT_0: - case R200_EMIT_VAP_CTL: case R200_EMIT_MATRIX_SELECT_0: case R200_EMIT_TEX_PROC_CTL_2: case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: -- cgit v1.2.3 From 255f3e6f76dfd267a14765dd1293229184298d89 Mon Sep 17 00:00:00 2001 From: Anish Mistry Date: Fri, 22 Sep 2006 03:43:34 +1000 Subject: bug 7092 : add pci ids for mach64 in Dell poweredge 4200 --- shared-core/drm_pciids.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index 9e0c0992..c597708d 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -186,6 +186,7 @@ 0x1002 0x4c51 0 "3D Rage LT Pro" 0x1002 0x4c42 0 "3D Rage LT Pro AGP-133" 0x1002 0x4c44 0 "3D Rage LT Pro AGP-66" +0x1002 0x4759 0 "Rage 3D IICATI 3D RAGE IIC AGP(A12/A13) 0x1002 0x474c 0 "Rage XC" 0x1002 0x474f 0 "Rage XL" 0x1002 0x4752 0 "Rage XL" -- cgit v1.2.3 From ab351505f36a6c66405ea7604378268848340a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 11 Aug 2006 17:57:59 +0200 Subject: Add support for secondary vertical blank interrupt to DRM core. --- shared-core/drm.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 87f8da6b..eaeb21e4 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -529,10 +529,12 @@ typedef struct drm_irq_busid { typedef enum { _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ } drm_vblank_seq_type_t; -#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY) struct drm_wait_vblank_request { drm_vblank_seq_type_t type; -- cgit v1.2.3 From 0c7d7f43610f705e8536a949cf2407efaa5ec217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 11 Aug 2006 18:06:46 +0200 Subject: Add support for secondary vertical blank interrupt to i915 driver. When the vertical blank interrupt is enabled for both pipes, pipe A is considered primary and pipe B secondary. When it's only enabled for one pipe, it's always considered primary for backwards compatibility. --- shared-core/i915_drv.h | 1 + shared-core/i915_irq.c | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index a87075b1..69cf8118 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -117,6 +117,7 @@ extern int i915_irq_emit(DRM_IOCTL_ARGS); extern int i915_irq_wait(DRM_IOCTL_ARGS); extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); +extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(drm_device_t * dev); extern void i915_driver_irq_postinstall(drm_device_t * dev); diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 14213b58..2eac29fc 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -60,7 +60,16 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev_priv->irq_queue); if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { - atomic_inc(&dev->vbl_received); + if ((dev_priv->vblank_pipe & + (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) + == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) { + if (temp & VSYNC_PIPEA_FLAG) + atomic_inc(&dev->vbl_received); + if (temp & VSYNC_PIPEB_FLAG) + atomic_inc(&dev->vbl_received2); + } else + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); } @@ -124,7 +133,8 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr) return ret; } -int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) +static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence, + atomic_t *counter) { drm_i915_private_t *dev_priv = dev->dev_private; unsigned int cur_vblank; @@ -136,7 +146,7 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) } DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, - (((cur_vblank = atomic_read(&dev->vbl_received)) + (((cur_vblank = atomic_read(counter)) - *sequence) <= (1<<23))); *sequence = cur_vblank; @@ -144,6 +154,16 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) return ret; } +int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) +{ + return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); +} + +int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence) +{ + return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2); +} + /* Needs the lock as it touches the ring. */ int i915_irq_emit(DRM_IOCTL_ARGS) -- cgit v1.2.3 From 29598e5253ff5c085ccf63580fd24b84db848424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 22 Aug 2006 16:40:07 +0200 Subject: Add support for tracking drawable information to core Actually make the existing ioctls for adding and removing drawables do something useful, and add another ioctl for the X server to update drawable information. The only kind of drawable information tracked so far is cliprects. --- shared-core/drm.h | 24 +++++ shared-core/drm_drawable.c | 256 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+) create mode 100644 shared-core/drm_drawable.c (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index eaeb21e4..614422bd 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -158,6 +158,14 @@ typedef struct drm_clip_rect { unsigned short y2; } drm_clip_rect_t; +/** + * Drawable information. + */ +typedef struct drm_drawable_info { + unsigned int num_rects; + drm_clip_rect_t *rects; +} drm_drawable_info_t; + /** * Texture region, */ @@ -507,6 +515,20 @@ typedef struct drm_draw { drm_drawable_t handle; } drm_draw_t; +/** + * DRM_IOCTL_UPDATE_DRAW ioctl argument type. + */ +typedef enum { + DRM_DRAWABLE_CLIPRECTS, +} drm_drawable_info_type_t; + +typedef struct drm_update_draw { + drm_drawable_t handle; + unsigned int type; + unsigned int num; + unsigned long long data; +} drm_update_draw_t; + /** * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. */ @@ -696,6 +718,8 @@ typedef struct drm_set_version { #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) +#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t) + /*@}*/ /** diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c new file mode 100644 index 00000000..ca6eb81c --- /dev/null +++ b/shared-core/drm_drawable.c @@ -0,0 +1,256 @@ +/** + * \file drm_drawable.c + * IOCTLs for drawables + * + * \author Rickard E. (Rik) Faith + * \author Gareth Hughes + * \author Michel Dänzer + */ + +/* + * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "drmP.h" + +/** No-op. */ +int drm_adddraw(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + unsigned int irqflags; + int i, j = 0; + drm_draw_t draw; + + spin_lock_irqsave(&dev->drw_lock, irqflags); + + for (i = 0; i < dev->drw_bitfield_length; i++) { + u32 bitfield = dev->drw_bitfield[i]; + + if (bitfield == ~0) + continue; + + for (; j < sizeof(bitfield); j++) + if (!(bitfield & (1 << j))) + goto done; + } +done: + + if (i == dev->drw_bitfield_length) { + u32 *new_bitfield = drm_realloc(dev->drw_bitfield, i * 4, + (i + 1) * 4, DRM_MEM_BUFS); + + if (!new_bitfield) { + DRM_ERROR("Failed to allocate new drawable bitfield\n"); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(ENOMEM); + } + + if (32 * (i + 1) > dev->drw_info_length) { + void *new_info = drm_realloc(dev->drw_info, + dev->drw_info_length * + sizeof(drm_drawable_info_t*), + 32 * (i + 1) * + sizeof(drm_drawable_info_t*), + DRM_MEM_BUFS); + + if (!new_info) { + DRM_ERROR("Failed to allocate new drawable info" + " array\n"); + + drm_free(new_bitfield, (i + 1) * 4, DRM_MEM_BUFS); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(ENOMEM); + } + + dev->drw_info = (drm_drawable_info_t**)new_info; + } + + new_bitfield[i] = 0; + + dev->drw_bitfield = new_bitfield; + dev->drw_bitfield_length++; + } + + dev->drw_bitfield[i] |= 1 << j; + + draw.handle = i * sizeof(u32) + j; + DRM_DEBUG("%d\n", draw.handle); + + dev->drw_info[draw.handle] = NULL; + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + + DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw)); + + return 0; +} + +/** No-op. */ +int drm_rmdraw(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_draw_t draw; + unsigned int idx, mod; + unsigned int irqflags; + + DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data, + sizeof(draw)); + + idx = draw.handle / 32; + mod = draw.handle % 32; + + spin_lock_irqsave(&dev->drw_lock, irqflags); + + if (idx >= dev->drw_bitfield_length || + !(dev->drw_bitfield[idx] & (1 << mod))) { + DRM_DEBUG("No such drawable %d\n", draw.handle); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return 0; + } + + dev->drw_bitfield[idx] &= ~(1 << mod); + + if (idx == (dev->drw_bitfield_length - 1)) { + while (idx >= 0 && !dev->drw_bitfield[idx]) + --idx; + + if (idx != draw.handle / 32) { + u32 *new_bitfield = drm_realloc(dev->drw_bitfield, + dev->drw_bitfield_length * 4, + (idx + 1) * 4, + DRM_MEM_BUFS); + + if (new_bitfield || idx == -1) { + dev->drw_bitfield = new_bitfield; + dev->drw_bitfield_length = idx + 1; + } + } + } + + if (32 * dev->drw_bitfield_length < dev->drw_info_length) { + void *new_info = drm_realloc(dev->drw_info, + dev->drw_info_length * + sizeof(drm_drawable_info_t*), + 32 * dev->drw_bitfield_length * + sizeof(drm_drawable_info_t*), + DRM_MEM_BUFS); + + if (new_info || !dev->drw_bitfield_length) { + dev->drw_info = (drm_drawable_info_t**)new_info; + dev->drw_info_length = 32 * dev->drw_bitfield_length; + } + } + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + + return 0; +} + +int drm_update_drawable_info(DRM_IOCTL_ARGS) { + DRM_DEVICE; + drm_update_draw_t update; + unsigned int id, idx, mod; + unsigned int irqflags; + drm_drawable_info_t *info; + void *new_data; + + DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data, + sizeof(update)); + + id = update.handle; + idx = id / 32; + mod = id % 32; + + spin_lock_irqsave(&dev->drw_lock, irqflags); + + if (idx >= dev->drw_bitfield_length || + !(dev->drw_bitfield[idx] & (1 << mod))) { + DRM_ERROR("No such drawable %d\n", update.handle); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(EINVAL); + } + + info = dev->drw_info[id]; + + if (!info) { + info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS); + + if (!info) { + DRM_ERROR("Failed to allocate drawable info memory\n"); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(ENOMEM); + } + + dev->drw_info[id] = info; + } + + switch (update.type) { + case DRM_DRAWABLE_CLIPRECTS: + new_data = drm_alloc(update.num * sizeof(drm_clip_rect_t), + DRM_MEM_BUFS); + + if (!new_data) { + DRM_ERROR("Failed to allocate cliprect memory\n"); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(ENOMEM); + } + + if (DRM_COPY_FROM_USER(new_data, + (drm_clip_rect_t __user *) + (unsigned long)update.data, + update.num * sizeof(drm_clip_rect_t))) { + DRM_ERROR("Failed to copy cliprects from userspace\n"); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(EFAULT); + } + + drm_free(info->rects, info->num_rects * sizeof(drm_clip_rect_t), + DRM_MEM_BUFS); + + info->rects = new_data; + info->num_rects = update.num; + break; + } + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + + return 0; +} + +/** + * Caller must hold the drawable spinlock! + */ +drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) { + unsigned int idx = id / 32, mod = id % 32; + + if (idx >= dev->drw_bitfield_length || + !(dev->drw_bitfield[idx] & (1 << mod))) { + DRM_DEBUG("No such drawable %d\n", id); + return NULL; + } + + return dev->drw_info[id]; +} -- cgit v1.2.3 From af48be1096221d551319c67a9e782b50ef58fefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 23 Aug 2006 16:04:41 +0200 Subject: Only reallocate cliprect memory if the number of cliprects changes. Also improve diagnostic output. --- shared-core/drm_drawable.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c index ca6eb81c..511f3eae 100644 --- a/shared-core/drm_drawable.c +++ b/shared-core/drm_drawable.c @@ -166,6 +166,7 @@ int drm_rmdraw(DRM_IOCTL_ARGS) spin_unlock_irqrestore(&dev->drw_lock, irqflags); + DRM_DEBUG("%d\n", draw.handle); return 0; } @@ -209,30 +210,42 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) { switch (update.type) { case DRM_DRAWABLE_CLIPRECTS: - new_data = drm_alloc(update.num * sizeof(drm_clip_rect_t), - DRM_MEM_BUFS); + if (update.num != info->num_rects) { + new_data = drm_alloc(update.num * + sizeof(drm_clip_rect_t), + DRM_MEM_BUFS); - if (!new_data) { - DRM_ERROR("Failed to allocate cliprect memory\n"); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - return DRM_ERR(ENOMEM); + if (!new_data) { + DRM_ERROR("Can't allocate cliprect memory\n"); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(ENOMEM); + } + + info->rects = new_data; } - if (DRM_COPY_FROM_USER(new_data, + if (DRM_COPY_FROM_USER(info->rects, (drm_clip_rect_t __user *) (unsigned long)update.data, update.num * sizeof(drm_clip_rect_t))) { - DRM_ERROR("Failed to copy cliprects from userspace\n"); + DRM_ERROR("Can't copy cliprects from userspace\n"); spin_unlock_irqrestore(&dev->drw_lock, irqflags); return DRM_ERR(EFAULT); } - drm_free(info->rects, info->num_rects * sizeof(drm_clip_rect_t), - DRM_MEM_BUFS); + if (update.num != info->num_rects) { + drm_free(info->rects, info->num_rects * + sizeof(drm_clip_rect_t), DRM_MEM_BUFS); + info->num_rects = update.num; + } - info->rects = new_data; - info->num_rects = update.num; + DRM_DEBUG("Updated %d cliprects for drawable %d\n", + info->num_rects, id); break; + default: + DRM_ERROR("Invalid update type %d\n", update.type); + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + return DRM_ERR(EINVAL); } spin_unlock_irqrestore(&dev->drw_lock, irqflags); -- cgit v1.2.3 From 43f8675534c7e95efbc92eaf2c8cc43aef95f125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 23 Aug 2006 19:00:26 +0200 Subject: Export drm_get_drawable_info symbol from core. --- shared-core/drm_drawable.c | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c index 511f3eae..0a357948 100644 --- a/shared-core/drm_drawable.c +++ b/shared-core/drm_drawable.c @@ -267,3 +267,4 @@ drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) return dev->drw_info[id]; } +EXPORT_SYMBOL(drm_get_drawable_info); -- cgit v1.2.3 From 23d2833aaa37a33b9ddcf06cc796f59befc0d360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 25 Aug 2006 18:55:55 +0200 Subject: Locking and memory management fixes. --- shared-core/drm_drawable.c | 261 ++++++++++++++++++++++++++------------------- 1 file changed, 154 insertions(+), 107 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c index 0a357948..81eb9f08 100644 --- a/shared-core/drm_drawable.c +++ b/shared-core/drm_drawable.c @@ -36,70 +36,86 @@ #include "drmP.h" -/** No-op. */ +/** + * Allocate drawable ID and memory to store information about it. + */ int drm_adddraw(DRM_IOCTL_ARGS) { DRM_DEVICE; unsigned int irqflags; - int i, j = 0; + int i, j; + u32 *bitfield = dev->drw_bitfield; + unsigned int bitfield_length = dev->drw_bitfield_length; + drm_drawable_info_t **info = dev->drw_info; + unsigned int info_length = dev->drw_info_length; drm_draw_t draw; - spin_lock_irqsave(&dev->drw_lock, irqflags); - - for (i = 0; i < dev->drw_bitfield_length; i++) { - u32 bitfield = dev->drw_bitfield[i]; - - if (bitfield == ~0) + for (i = 0, j = 0; i < bitfield_length; i++) { + if (bitfield[i] == ~0) continue; - for (; j < sizeof(bitfield); j++) - if (!(bitfield & (1 << j))) + for (; j < 8 * sizeof(*bitfield); j++) + if (!(bitfield[i] & (1 << j))) goto done; } done: - if (i == dev->drw_bitfield_length) { - u32 *new_bitfield = drm_realloc(dev->drw_bitfield, i * 4, - (i + 1) * 4, DRM_MEM_BUFS); + if (i == bitfield_length) { + bitfield_length++; + + bitfield = drm_alloc(bitfield_length * sizeof(*bitfield), + DRM_MEM_BUFS); - if (!new_bitfield) { + if (!bitfield) { DRM_ERROR("Failed to allocate new drawable bitfield\n"); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); return DRM_ERR(ENOMEM); } - if (32 * (i + 1) > dev->drw_info_length) { - void *new_info = drm_realloc(dev->drw_info, - dev->drw_info_length * - sizeof(drm_drawable_info_t*), - 32 * (i + 1) * - sizeof(drm_drawable_info_t*), - DRM_MEM_BUFS); + if (8 * sizeof(*bitfield) * bitfield_length > info_length) { + info_length += 8 * sizeof(*bitfield); - if (!new_info) { + info = drm_alloc(info_length * sizeof(*info), + DRM_MEM_BUFS); + + if (!info) { DRM_ERROR("Failed to allocate new drawable info" " array\n"); - drm_free(new_bitfield, (i + 1) * 4, DRM_MEM_BUFS); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); + drm_free(bitfield, + bitfield_length * sizeof(*bitfield), + DRM_MEM_BUFS); return DRM_ERR(ENOMEM); } - - dev->drw_info = (drm_drawable_info_t**)new_info; } - new_bitfield[i] = 0; - - dev->drw_bitfield = new_bitfield; - dev->drw_bitfield_length++; + bitfield[i] = 0; } - dev->drw_bitfield[i] |= 1 << j; - - draw.handle = i * sizeof(u32) + j; + draw.handle = i * 8 * sizeof(*bitfield) + j; DRM_DEBUG("%d\n", draw.handle); - dev->drw_info[draw.handle] = NULL; + spin_lock_irqsave(&dev->drw_lock, irqflags); + + bitfield[i] |= 1 << j; + info[draw.handle] = NULL; + + if (bitfield != dev->drw_bitfield) { + memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length * + sizeof(*bitfield)); + drm_free(dev->drw_bitfield, sizeof(*bitfield) * + dev->drw_bitfield_length, DRM_MEM_BUFS); + dev->drw_bitfield = bitfield; + dev->drw_bitfield_length = bitfield_length; + } + + if (info != dev->drw_info) { + memcpy(info, dev->drw_info, dev->drw_info_length * + sizeof(*info)); + drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length, + DRM_MEM_BUFS); + dev->drw_info = info; + dev->drw_info_length = info_length; + } spin_unlock_irqrestore(&dev->drw_lock, irqflags); @@ -108,63 +124,85 @@ done: return 0; } -/** No-op. */ +/** + * Free drawable ID and memory to store information about it. + */ int drm_rmdraw(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_draw_t draw; - unsigned int idx, mod; + unsigned int idx, shift; unsigned int irqflags; + u32 *bitfield = dev->drw_bitfield; + unsigned int bitfield_length = dev->drw_bitfield_length; + drm_drawable_info_t **info = dev->drw_info; + unsigned int info_length = dev->drw_info_length; DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data, sizeof(draw)); - idx = draw.handle / 32; - mod = draw.handle % 32; + idx = draw.handle / (8 * sizeof(*bitfield)); + shift = draw.handle % (8 * sizeof(*bitfield)); - spin_lock_irqsave(&dev->drw_lock, irqflags); - - if (idx >= dev->drw_bitfield_length || - !(dev->drw_bitfield[idx] & (1 << mod))) { + if (idx >= bitfield_length || + !(bitfield[idx] & (1 << shift))) { DRM_DEBUG("No such drawable %d\n", draw.handle); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); return 0; } - dev->drw_bitfield[idx] &= ~(1 << mod); + spin_lock_irqsave(&dev->drw_lock, irqflags); + + bitfield[idx] &= ~(1 << shift); + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); - if (idx == (dev->drw_bitfield_length - 1)) { - while (idx >= 0 && !dev->drw_bitfield[idx]) + /* Can we shrink the arrays? */ + if (idx == bitfield_length - 1) { + while (idx >= 0 && !bitfield[idx]) --idx; - if (idx != draw.handle / 32) { - u32 *new_bitfield = drm_realloc(dev->drw_bitfield, - dev->drw_bitfield_length * 4, - (idx + 1) * 4, - DRM_MEM_BUFS); + bitfield_length = idx + 1; - if (new_bitfield || idx == -1) { - dev->drw_bitfield = new_bitfield; - dev->drw_bitfield_length = idx + 1; - } + if (idx != draw.handle / (8 * sizeof(*bitfield))) + bitfield = drm_alloc(bitfield_length * + sizeof(*bitfield), DRM_MEM_BUFS); + + if (!bitfield && bitfield_length) { + bitfield = dev->drw_bitfield; + bitfield_length = dev->drw_bitfield_length; } } - if (32 * dev->drw_bitfield_length < dev->drw_info_length) { - void *new_info = drm_realloc(dev->drw_info, - dev->drw_info_length * - sizeof(drm_drawable_info_t*), - 32 * dev->drw_bitfield_length * - sizeof(drm_drawable_info_t*), - DRM_MEM_BUFS); - - if (new_info || !dev->drw_bitfield_length) { - dev->drw_info = (drm_drawable_info_t**)new_info; - dev->drw_info_length = 32 * dev->drw_bitfield_length; + if (bitfield != dev->drw_bitfield) { + info_length = 8 * sizeof(*bitfield) * bitfield_length; + + info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS); + + if (!info && info_length) { + info = dev->drw_info; + info_length = dev->drw_info_length; } - } - spin_unlock_irqrestore(&dev->drw_lock, irqflags); + spin_lock_irqsave(&dev->drw_lock, irqflags); + + memcpy(bitfield, dev->drw_bitfield, bitfield_length * + sizeof(*bitfield)); + drm_free(dev->drw_bitfield, sizeof(*bitfield) * + dev->drw_bitfield_length, DRM_MEM_BUFS); + dev->drw_bitfield = bitfield; + dev->drw_bitfield_length = bitfield_length; + + if (info != dev->drw_info) { + memcpy(info, dev->drw_info, info_length * + sizeof(*info)); + drm_free(dev->drw_info, sizeof(*info) * + dev->drw_info_length, DRM_MEM_BUFS); + dev->drw_info = info; + dev->drw_info_length = info_length; + } + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + } DRM_DEBUG("%d\n", draw.handle); return 0; @@ -173,24 +211,22 @@ int drm_rmdraw(DRM_IOCTL_ARGS) int drm_update_drawable_info(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_update_draw_t update; - unsigned int id, idx, mod; - unsigned int irqflags; + unsigned int id, idx, shift; + u32 *bitfield = dev->drw_bitfield; + unsigned int irqflags, bitfield_length = dev->drw_bitfield_length; drm_drawable_info_t *info; - void *new_data; + drm_clip_rect_t *rects; + int err; DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data, sizeof(update)); id = update.handle; - idx = id / 32; - mod = id % 32; + idx = id / (8 * sizeof(*bitfield)); + shift = id % (8 * sizeof(*bitfield)); - spin_lock_irqsave(&dev->drw_lock, irqflags); - - if (idx >= dev->drw_bitfield_length || - !(dev->drw_bitfield[idx] & (1 << mod))) { + if (idx >= bitfield_length || !(bitfield[idx] & (1 << shift))) { DRM_ERROR("No such drawable %d\n", update.handle); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); return DRM_ERR(EINVAL); } @@ -201,66 +237,77 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) { if (!info) { DRM_ERROR("Failed to allocate drawable info memory\n"); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); return DRM_ERR(ENOMEM); } - - dev->drw_info[id] = info; } switch (update.type) { case DRM_DRAWABLE_CLIPRECTS: if (update.num != info->num_rects) { - new_data = drm_alloc(update.num * - sizeof(drm_clip_rect_t), - DRM_MEM_BUFS); - - if (!new_data) { - DRM_ERROR("Can't allocate cliprect memory\n"); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - return DRM_ERR(ENOMEM); - } - - info->rects = new_data; + rects = drm_alloc(update.num * sizeof(drm_clip_rect_t), + DRM_MEM_BUFS); + } else + rects = info->rects; + + if (update.num && !rects) { + DRM_ERROR("Failed to allocate cliprect memory\n"); + err = DRM_ERR(ENOMEM); + goto error; } - if (DRM_COPY_FROM_USER(info->rects, - (drm_clip_rect_t __user *) - (unsigned long)update.data, - update.num * sizeof(drm_clip_rect_t))) { - DRM_ERROR("Can't copy cliprects from userspace\n"); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - return DRM_ERR(EFAULT); + if (update.num && DRM_COPY_FROM_USER(rects, + (drm_clip_rect_t __user *) + (unsigned long)update.data, + update.num * + sizeof(*rects))) { + DRM_ERROR("Failed to copy cliprects from userspace\n"); + err = DRM_ERR(EFAULT); + goto error; } - if (update.num != info->num_rects) { + spin_lock_irqsave(&dev->drw_lock, irqflags); + + if (rects != info->rects) { drm_free(info->rects, info->num_rects * sizeof(drm_clip_rect_t), DRM_MEM_BUFS); - info->num_rects = update.num; } + info->rects = rects; + info->num_rects = update.num; + dev->drw_info[id] = info; + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + DRM_DEBUG("Updated %d cliprects for drawable %d\n", info->num_rects, id); break; default: DRM_ERROR("Invalid update type %d\n", update.type); - spin_unlock_irqrestore(&dev->drw_lock, irqflags); return DRM_ERR(EINVAL); } - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - return 0; + +error: + if (!dev->drw_info[id]) + drm_free(info, sizeof(*info), DRM_MEM_BUFS); + else if (rects != dev->drw_info[id]->rects) + drm_free(rects, update.num * + sizeof(drm_clip_rect_t), DRM_MEM_BUFS); + + return err; } /** * Caller must hold the drawable spinlock! */ drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) { - unsigned int idx = id / 32, mod = id % 32; + u32 *bitfield = dev->drw_bitfield; + unsigned int idx = id / (8 * sizeof(*bitfield)); + unsigned int shift = id % (8 * sizeof(*bitfield)); if (idx >= dev->drw_bitfield_length || - !(dev->drw_bitfield[idx] & (1 << mod))) { + !(bitfield[idx] & (1 << shift))) { DRM_DEBUG("No such drawable %d\n", id); return NULL; } -- cgit v1.2.3 From 257771fa290b62d4d2ad896843cf3a207978d0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 25 Aug 2006 19:01:05 +0200 Subject: i915: Add ioctl for scheduling buffer swaps at vertical blanks. This uses the core facility to schedule a driver callback that will be called ASAP after the given vertical blank interrupt with the HW lock held. --- shared-core/i915_dma.c | 2 + shared-core/i915_drm.h | 9 +++ shared-core/i915_drv.h | 17 +++++ shared-core/i915_irq.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 211 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3863490c..be235c17 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -163,6 +163,7 @@ static int i915_initialize(drm_device_t * dev, dev_priv->ring.virtual_start = dev_priv->ring.map.handle; + dev_priv->cpp = init->cpp; dev_priv->back_offset = init->back_offset; dev_priv->front_offset = init->front_offset; dev_priv->current_page = 0; @@ -797,6 +798,7 @@ drm_ioctl_desc_t i915_ioctls[] = { [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, + [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH}, }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index fcffb25c..7e4ba13d 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -132,6 +132,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_DESTROY_HEAP 0x0c #define DRM_I915_SET_VBLANK_PIPE 0x0d #define DRM_I915_GET_VBLANK_PIPE 0x0e +#define DRM_I915_VBLANK_SWAP 0x0f #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -244,4 +245,12 @@ typedef struct drm_i915_vblank_pipe { int pipe; } drm_i915_vblank_pipe_t; +/* Schedule buffer swap at given vertical blank: + */ +typedef struct drm_i915_vblank_swap { + drm_drawable_t drawable; + unsigned int pipe; + unsigned int sequence; +} drm_i915_vblank_swap_t; + #endif /* _I915_DRM_H_ */ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 69cf8118..dc9bbc5c 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -71,6 +71,13 @@ struct mem_block { DRMFILE filp; /* 0: free, -1: heap, other: real files */ }; +typedef struct _drm_i915_vbl_swap { + struct list_head head; + drm_drawable_t drw_id; + unsigned int pipe; + unsigned int sequence; +} drm_i915_vbl_swap_t; + typedef struct drm_i915_private { drm_local_map_t *sarea; drm_local_map_t *mmio_map; @@ -83,6 +90,7 @@ typedef struct drm_i915_private { dma_addr_t dma_status_page; unsigned long counter; + unsigned int cpp; int back_offset; int front_offset; int current_page; @@ -98,6 +106,10 @@ typedef struct drm_i915_private { struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; + + spinlock_t swaps_lock; + drm_i915_vbl_swap_t vbl_swaps; + unsigned int swaps_pending; } drm_i915_private_t; extern drm_ioctl_desc_t i915_ioctls[]; @@ -124,6 +136,7 @@ extern void i915_driver_irq_postinstall(drm_device_t * dev); extern void i915_driver_irq_uninstall(drm_device_t * dev); extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); +extern int i915_vblank_swap(DRM_IOCTL_ARGS); /* i915_mem.c */ extern int i915_mem_alloc(DRM_IOCTL_ARGS); @@ -257,6 +270,10 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) +#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) +#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) +#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) + #define MI_BATCH_BUFFER ((0x30<<23)|1) #define MI_BATCH_BUFFER_START (0x31<<23) #define MI_BATCH_BUFFER_END (0xA<<23) diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 2eac29fc..39d8c386 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -37,6 +37,99 @@ #define MAX_NOPID ((u32)~0) +/** + * Emit blits for scheduled buffer swaps. + * + * This function will be called with the HW lock held. + */ +static void i915_vblank_tasklet(drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned int irqflags; + struct list_head *list, *tmp; + + DRM_DEBUG("\n"); + + spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + + list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { + drm_i915_vbl_swap_t *vbl_swap = + list_entry(list, drm_i915_vbl_swap_t, head); + atomic_t *counter = vbl_swap->pipe ? &dev->vbl_received2 : + &dev->vbl_received; + + if ((atomic_read(counter) - vbl_swap->sequence) <= (1<<23)) { + drm_drawable_info_t *drw; + + spin_unlock(&dev_priv->swaps_lock); + + spin_lock(&dev->drw_lock); + + drw = drm_get_drawable_info(dev, vbl_swap->drw_id); + + if (drw) { + int i, num_rects = drw->num_rects; + drm_clip_rect_t *rect = drw->rects; + drm_i915_sarea_t *sarea_priv = + dev_priv->sarea_priv; + u32 cpp = dev_priv->cpp; + u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | + XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB) + : XY_SRC_COPY_BLT_CMD; + u32 pitchropcpp = (sarea_priv->pitch * cpp) | + (0xcc << 16) | (cpp << 23) | + (1 << 24); + RING_LOCALS; + + i915_kernel_lost_context(dev); + + BEGIN_LP_RING(6); + + OUT_RING(GFX_OP_DRAWRECT_INFO); + OUT_RING(0); + OUT_RING(0); + OUT_RING(sarea_priv->width | + sarea_priv->height << 16); + OUT_RING(sarea_priv->width | + sarea_priv->height << 16); + OUT_RING(0); + + ADVANCE_LP_RING(); + + sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; + + for (i = 0; i < num_rects; i++, rect++) { + BEGIN_LP_RING(8); + + OUT_RING(cmd); + OUT_RING(pitchropcpp); + OUT_RING((rect->y1 << 16) | rect->x1); + OUT_RING((rect->y2 << 16) | rect->x2); + OUT_RING(sarea_priv->front_offset); + OUT_RING((rect->y1 << 16) | rect->x1); + OUT_RING(pitchropcpp & 0xffff); + OUT_RING(sarea_priv->back_offset); + + ADVANCE_LP_RING(); + } + } + + spin_unlock(&dev->drw_lock); + + spin_lock(&dev_priv->swaps_lock); + + list_del(list); + + drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); + + dev_priv->swaps_pending--; + } + } + + spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); +} + irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { drm_device_t *dev = (drm_device_t *) arg; @@ -72,6 +165,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); + + drm_locked_tasklet(dev, i915_vblank_tasklet); } return IRQ_HANDLED; @@ -274,6 +369,90 @@ int i915_vblank_pipe_get(DRM_IOCTL_ARGS) return 0; } +/** + * Schedule buffer swap at given vertical blank. + */ +int i915_vblank_swap(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_vblank_swap_t swap; + drm_i915_vbl_swap_t *vbl_swap; + unsigned int irqflags; + struct list_head *list; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __func__); + return DRM_ERR(EINVAL); + } + + if (dev_priv->sarea_priv->rotation) { + DRM_DEBUG("Rotation not supported\n"); + return DRM_ERR(EINVAL); + } + + if (dev_priv->swaps_pending >= 100) { + DRM_DEBUG("Too many swaps queued\n"); + return DRM_ERR(EBUSY); + } + + DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, + sizeof(swap)); + + if (swap.pipe > 1 || !(dev_priv->vblank_pipe & (1 << swap.pipe))) { + DRM_ERROR("Invalid pipe %d\n", swap.pipe); + return DRM_ERR(EINVAL); + } + + spin_lock_irqsave(&dev->drw_lock, irqflags); + + if (!drm_get_drawable_info(dev, swap.drawable)) { + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + DRM_ERROR("Invalid drawable ID %d\n", swap.drawable); + return DRM_ERR(EINVAL); + } + + spin_unlock_irqrestore(&dev->drw_lock, irqflags); + + spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + + list_for_each(list, &dev_priv->vbl_swaps.head) { + vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); + + if (vbl_swap->drw_id == swap.drawable && + vbl_swap->pipe == swap.pipe && + vbl_swap->sequence == swap.sequence) { + spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + DRM_DEBUG("Already scheduled\n"); + return 0; + } + } + + spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + + vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER); + + if (!vbl_swap) { + DRM_ERROR("Failed to allocate memory to queue swap\n"); + return DRM_ERR(ENOMEM); + } + + DRM_DEBUG("\n"); + + vbl_swap->drw_id = swap.drawable; + vbl_swap->pipe = swap.pipe; + vbl_swap->sequence = swap.sequence; + + spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + + list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head); + dev_priv->swaps_pending++; + + spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + + return 0; +} + /* drm_dma.h hooks */ void i915_driver_irq_preinstall(drm_device_t * dev) @@ -289,6 +468,10 @@ void i915_driver_irq_postinstall(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); + dev_priv->swaps_pending = 0; + i915_enable_interrupt(dev); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); } -- cgit v1.2.3 From d04751facea36cb888c7510b126658fdbc4277d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Mon, 28 Aug 2006 18:19:58 +0200 Subject: Add copyright notice. --- shared-core/drm_drawable.c | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c index 81eb9f08..bbfaf139 100644 --- a/shared-core/drm_drawable.c +++ b/shared-core/drm_drawable.c @@ -12,6 +12,7 @@ * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a -- cgit v1.2.3 From df7551ef7334d728ec0371423661bb403d3e270a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 30 Aug 2006 19:24:04 +0200 Subject: Change first valid DRM drawable ID to be 1 instead of 0. This makes it easier for userspace to know when it needs to allocate an ID. Also free drawable information memory when it's no longer needed. --- shared-core/drm_drawable.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c index bbfaf139..5e2fc86c 100644 --- a/shared-core/drm_drawable.c +++ b/shared-core/drm_drawable.c @@ -92,13 +92,13 @@ done: bitfield[i] = 0; } - draw.handle = i * 8 * sizeof(*bitfield) + j; + draw.handle = i * 8 * sizeof(*bitfield) + j + 1; DRM_DEBUG("%d\n", draw.handle); spin_lock_irqsave(&dev->drw_lock, irqflags); bitfield[i] |= 1 << j; - info[draw.handle] = NULL; + info[draw.handle - 1] = NULL; if (bitfield != dev->drw_bitfield) { memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length * @@ -132,7 +132,7 @@ int drm_rmdraw(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_draw_t draw; - unsigned int idx, shift; + unsigned int id, idx, shift; unsigned int irqflags; u32 *bitfield = dev->drw_bitfield; unsigned int bitfield_length = dev->drw_bitfield_length; @@ -142,10 +142,11 @@ int drm_rmdraw(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data, sizeof(draw)); - idx = draw.handle / (8 * sizeof(*bitfield)); - shift = draw.handle % (8 * sizeof(*bitfield)); + id = draw.handle - 1; + idx = id / (8 * sizeof(*bitfield)); + shift = id % (8 * sizeof(*bitfield)); - if (idx >= bitfield_length || + if (idx < 0 || idx >= bitfield_length || !(bitfield[idx] & (1 << shift))) { DRM_DEBUG("No such drawable %d\n", draw.handle); return 0; @@ -157,6 +158,12 @@ int drm_rmdraw(DRM_IOCTL_ARGS) spin_unlock_irqrestore(&dev->drw_lock, irqflags); + if (info[id]) { + drm_free(info[id]->rects, info[id]->num_rects * + sizeof(drm_clip_rect_t), DRM_MEM_BUFS); + drm_free(info[id], sizeof(**info), DRM_MEM_BUFS); + } + /* Can we shrink the arrays? */ if (idx == bitfield_length - 1) { while (idx >= 0 && !bitfield[idx]) @@ -164,7 +171,7 @@ int drm_rmdraw(DRM_IOCTL_ARGS) bitfield_length = idx + 1; - if (idx != draw.handle / (8 * sizeof(*bitfield))) + if (idx != id / (8 * sizeof(*bitfield))) bitfield = drm_alloc(bitfield_length * sizeof(*bitfield), DRM_MEM_BUFS); @@ -222,11 +229,12 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) { DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data, sizeof(update)); - id = update.handle; + id = update.handle - 1; idx = id / (8 * sizeof(*bitfield)); shift = id % (8 * sizeof(*bitfield)); - if (idx >= bitfield_length || !(bitfield[idx] & (1 << shift))) { + if (idx < 0 || idx >= bitfield_length || + !(bitfield[idx] & (1 << shift))) { DRM_ERROR("No such drawable %d\n", update.handle); return DRM_ERR(EINVAL); } @@ -304,10 +312,13 @@ error: */ drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) { u32 *bitfield = dev->drw_bitfield; - unsigned int idx = id / (8 * sizeof(*bitfield)); - unsigned int shift = id % (8 * sizeof(*bitfield)); + unsigned int idx, shift; + + id--; + idx = id / (8 * sizeof(*bitfield)); + shift = id % (8 * sizeof(*bitfield)); - if (idx >= dev->drw_bitfield_length || + if (idx < 0 || idx >= dev->drw_bitfield_length || !(bitfield[idx] & (1 << shift))) { DRM_DEBUG("No such drawable %d\n", id); return NULL; -- cgit v1.2.3 From d5a0f107511e128658e2d5e15bd7e6215c507f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 30 Aug 2006 19:33:28 +0200 Subject: DRM_I915_VBLANK_SWAP ioctl: Take drm_vblank_seq_type_t instead of pipe number. Handle relative as well as absolute target sequence numbers. Return error if target sequence has already passed, so userspace can deal with this situation as it sees fit. On success, return the sequence number of the vertical blank when the buffer swap is expected to take place. Also add DRM_IOCTL_I915_VBLANK_SWAP definition for userspace code that may want to use ioctl() instead of drmCommandWriteRead(). --- shared-core/i915_drm.h | 3 ++- shared-core/i915_irq.c | 43 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 6 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 7e4ba13d..3a39d531 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -149,6 +149,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) +#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) /* Allow drivers to submit batchbuffers directly to hardware, relying @@ -249,7 +250,7 @@ typedef struct drm_i915_vblank_pipe { */ typedef struct drm_i915_vblank_swap { drm_drawable_t drawable; - unsigned int pipe; + drm_vblank_seq_type_t seqtype; unsigned int sequence; } drm_i915_vblank_swap_t; diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 39d8c386..6f00febc 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -378,7 +378,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_vblank_swap_t swap; drm_i915_vbl_swap_t *vbl_swap; - unsigned int irqflags; + unsigned int pipe, seqtype, irqflags, curseq; struct list_head *list; if (!dev_priv) { @@ -399,8 +399,23 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, sizeof(swap)); - if (swap.pipe > 1 || !(dev_priv->vblank_pipe & (1 << swap.pipe))) { - DRM_ERROR("Invalid pipe %d\n", swap.pipe); + if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | + _DRM_VBLANK_SECONDARY)) { + DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype); + return DRM_ERR(EINVAL); + } + + pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; + + seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); + + if (seqtype == _DRM_VBLANK_RELATIVE && swap.sequence == 0) { + DRM_DEBUG("Not scheduling swap for current sequence\n"); + return DRM_ERR(EINVAL); + } + + if (!(dev_priv->vblank_pipe & (1 << pipe))) { + DRM_ERROR("Invalid pipe %d\n", pipe); return DRM_ERR(EINVAL); } @@ -414,13 +429,28 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) spin_unlock_irqrestore(&dev->drw_lock, irqflags); + curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); + spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + switch (seqtype) { + case _DRM_VBLANK_RELATIVE: + swap.sequence += curseq; + break; + case _DRM_VBLANK_ABSOLUTE: + if ((curseq - swap.sequence) > (1<<23)) { + spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + DRM_DEBUG("Missed target sequence\n"); + return DRM_ERR(EINVAL); + } + break; + } + list_for_each(list, &dev_priv->vbl_swaps.head) { vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); if (vbl_swap->drw_id == swap.drawable && - vbl_swap->pipe == swap.pipe && + vbl_swap->pipe == pipe && vbl_swap->sequence == swap.sequence) { spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); DRM_DEBUG("Already scheduled\n"); @@ -440,7 +470,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) DRM_DEBUG("\n"); vbl_swap->drw_id = swap.drawable; - vbl_swap->pipe = swap.pipe; + vbl_swap->pipe = pipe; vbl_swap->sequence = swap.sequence; spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); @@ -450,6 +480,9 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap, + sizeof(swap)); + return 0; } -- cgit v1.2.3 From 87c57cba1a70221fc570b253bf3b24682ef6b894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 31 Aug 2006 18:30:55 +0200 Subject: Make handling of dev_priv->vblank_pipe more robust. Initialize it to default value if it hasn't been set by the X server yet. In i915_vblank_pipe_set(), only update dev_priv->vblank_pipe and call i915_enable_interrupt() if the argument passed from userspace is valid to avoid corrupting dev_priv->vblank_pipe on invalid arguments. --- shared-core/i915_irq.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 6f00febc..68e7c668 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -307,7 +307,7 @@ int i915_irq_wait(DRM_IOCTL_ARGS) return i915_wait_irq(dev, irqwait.irq_seq); } -static int i915_enable_interrupt (drm_device_t *dev) +static void i915_enable_interrupt (drm_device_t *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u16 flag; @@ -317,13 +317,8 @@ static int i915_enable_interrupt (drm_device_t *dev) flag |= VSYNC_PIPEA_FLAG; if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) flag |= VSYNC_PIPEB_FLAG; - if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { - DRM_ERROR("%s called with invalid pipe 0x%x\n", - __FUNCTION__, dev_priv->vblank_pipe); - return DRM_ERR(EINVAL); - } + I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); - return 0; } /* Set the vblank monitor pipe @@ -342,8 +337,17 @@ int i915_vblank_pipe_set(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, sizeof(pipe)); + if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { + DRM_ERROR("%s called with invalid pipe 0x%x\n", + __FUNCTION__, pipe.pipe); + return DRM_ERR(EINVAL); + } + dev_priv->vblank_pipe = pipe.pipe; - return i915_enable_interrupt (dev); + + i915_enable_interrupt (dev); + + return 0; } int i915_vblank_pipe_get(DRM_IOCTL_ARGS) @@ -505,6 +509,8 @@ void i915_driver_irq_postinstall(drm_device_t * dev) INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); dev_priv->swaps_pending = 0; + if (!dev_priv->vblank_pipe) + dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; i915_enable_interrupt(dev); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); } -- cgit v1.2.3 From c2bdb76814755c9ac6e66a8815f23af0fe4f3a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 31 Aug 2006 18:33:04 +0200 Subject: Add SAREA fileds for determining which pipe to sync window buffer swaps to. --- shared-core/i915_drm.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'shared-core') diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 3a39d531..358b11e2 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -104,6 +104,15 @@ typedef struct _drm_i915_sarea { unsigned int depth_tiled; unsigned int rotated_tiled; unsigned int rotated2_tiled; + + int pipeA_x; + int pipeA_y; + int pipeA_w; + int pipeA_h; + int pipeB_x; + int pipeB_y; + int pipeB_w; + int pipeB_h; } drm_i915_sarea_t; /* Flags for perf_boxes -- cgit v1.2.3 From 7f09f957d9a61ac107f8fd29128d7899a3e8a228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 1 Sep 2006 11:24:38 +0200 Subject: Fix 'sequence has passed' condition in i915_vblank_swap(). --- shared-core/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 68e7c668..9cd8ece4 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -442,7 +442,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) swap.sequence += curseq; break; case _DRM_VBLANK_ABSOLUTE: - if ((curseq - swap.sequence) > (1<<23)) { + if ((curseq - swap.sequence) <= (1<<23)) { spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); DRM_DEBUG("Missed target sequence\n"); return DRM_ERR(EINVAL); -- cgit v1.2.3 From 89e323e4900af84cc33219ad24eb0b435a039d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 1 Sep 2006 11:27:14 +0200 Subject: Core vsync: Add flag DRM_VBLANK_NEXTONMISS. When this flag is set and the target sequence is missed, wait for the next vertical blank instead of returning immediately. --- shared-core/drm.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 614422bd..7f90a96d 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -551,12 +551,14 @@ typedef struct drm_irq_busid { typedef enum { _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ } drm_vblank_seq_type_t; #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) -#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \ + _DRM_VBLANK_NEXTONMISS) struct drm_wait_vblank_request { drm_vblank_seq_type_t type; -- cgit v1.2.3 From 50a0284a61d4415c0ebdb02decee76ef3115007a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 1 Sep 2006 11:48:07 +0200 Subject: Only return EBUSY after we've established we need to schedule a new swap. --- shared-core/i915_irq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 9cd8ece4..d32f592f 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -395,11 +395,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) return DRM_ERR(EINVAL); } - if (dev_priv->swaps_pending >= 100) { - DRM_DEBUG("Too many swaps queued\n"); - return DRM_ERR(EBUSY); - } - DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, sizeof(swap)); @@ -464,6 +459,11 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + if (dev_priv->swaps_pending >= 100) { + DRM_DEBUG("Too many swaps queued\n"); + return DRM_ERR(EBUSY); + } + vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER); if (!vbl_swap) { -- cgit v1.2.3 From 0356fe260dcf80f6d2d20e3384f2a1f4ee7f5b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 13 Sep 2006 08:59:35 +0200 Subject: i915_vblank_swap: Add support for DRM_VBLANK_NEXTONMISS. --- shared-core/i915_irq.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index d32f592f..9db38706 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -399,7 +399,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) sizeof(swap)); if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | - _DRM_VBLANK_SECONDARY)) { + _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) { DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype); return DRM_ERR(EINVAL); } @@ -408,11 +408,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); - if (seqtype == _DRM_VBLANK_RELATIVE && swap.sequence == 0) { - DRM_DEBUG("Not scheduling swap for current sequence\n"); - return DRM_ERR(EINVAL); - } - if (!(dev_priv->vblank_pipe & (1 << pipe))) { DRM_ERROR("Invalid pipe %d\n", pipe); return DRM_ERR(EINVAL); @@ -430,21 +425,20 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); - spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); - - switch (seqtype) { - case _DRM_VBLANK_RELATIVE: + if (seqtype == _DRM_VBLANK_RELATIVE) swap.sequence += curseq; - break; - case _DRM_VBLANK_ABSOLUTE: - if ((curseq - swap.sequence) <= (1<<23)) { - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); + + if ((curseq - swap.sequence) <= (1<<23)) { + if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) { + swap.sequence = curseq + 1; + } else { DRM_DEBUG("Missed target sequence\n"); return DRM_ERR(EINVAL); } - break; } + spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); + list_for_each(list, &dev_priv->vbl_swaps.head) { vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); -- cgit v1.2.3 From 2627131e5d0c8cd5e3f0db06451c2e7ae7569b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Mon, 18 Sep 2006 12:15:38 +0200 Subject: i915: Bump minor for swap scheduling ioctl and secondary vblank support. --- shared-core/i915_drv.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index dc9bbc5c..de7f8224 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -46,9 +46,11 @@ * 1.3: Add vblank support * 1.4: Fix cmdbuffer path, add heap destroy * 1.5: Add vblank pipe configuration + * 1.6: - New ioctl for scheduling buffer swaps on vertical blank + * - Support vertical blank on secondary display pipe */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 5 +#define DRIVER_MINOR 6 #define DRIVER_PATCHLEVEL 0 typedef struct _drm_i915_ring_buffer { -- cgit v1.2.3 From 881ba569929ceafd42e3c86228b0172099083d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 27 Sep 2006 18:22:10 +0200 Subject: i915: Avoid mis-counting vblank interrupts when they're only enabled for pipe A. It looks like 'after a while', I915REG_INT_IDENTITY_R for some reason always has VSYNC_PIPEB_FLAG set in the interrupt handler, even though pipe B is disabled. So we only increase dev->vbl_received if the corresponding bit is also set in dev->vblank_pipe. --- shared-core/i915_irq.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 9db38706..fbc66749 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -153,14 +153,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev_priv->irq_queue); if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { - if ((dev_priv->vblank_pipe & + int vblank_pipe = dev_priv->vblank_pipe; + + if ((vblank_pipe & (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) { if (temp & VSYNC_PIPEA_FLAG) atomic_inc(&dev->vbl_received); if (temp & VSYNC_PIPEB_FLAG) atomic_inc(&dev->vbl_received2); - } else + } else if (((temp & VSYNC_PIPEA_FLAG) && + (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) || + ((temp & VSYNC_PIPEB_FLAG) && + (vblank_pipe & DRM_I915_VBLANK_PIPE_B))) atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); -- cgit v1.2.3 From 7af93dd9849442270ec89cb4bbeef5bfd4f9e424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 29 Sep 2006 10:27:29 +0200 Subject: i915: Only schedule vblank tasklet if there are scheduled swaps pending. This fixes issues on X server startup with versions of xf86-video-intel that enable the IRQ before they have a context ID. --- shared-core/i915_irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index fbc66749..76c3a810 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -171,7 +171,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); - drm_locked_tasklet(dev, i915_vblank_tasklet); + if (dev_priv->swaps_pending > 0) + drm_locked_tasklet(dev, i915_vblank_tasklet); } return IRQ_HANDLED; -- cgit v1.2.3 From d58389968124191a546a14b42ef84edc224be23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20K=C3=BChling?= Date: Mon, 2 Oct 2006 10:50:40 +0200 Subject: drm_rmdraw: Declare id and idx as signed so testing for < 0 works as intended. --- shared-core/drm_drawable.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c index 5e2fc86c..d203b244 100644 --- a/shared-core/drm_drawable.c +++ b/shared-core/drm_drawable.c @@ -132,7 +132,8 @@ int drm_rmdraw(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_draw_t draw; - unsigned int id, idx, shift; + int id, idx; + unsigned int shift; unsigned int irqflags; u32 *bitfield = dev->drw_bitfield; unsigned int bitfield_length = dev->drw_bitfield_length; -- cgit v1.2.3 From f6238cf6244b32bd84e3d2819963d7f5473867c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Mon, 2 Oct 2006 15:33:19 +0200 Subject: Fix type of second argument to spin_lock_irqsave(). --- shared-core/drm_drawable.c | 8 ++++---- shared-core/i915_irq.c | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm_drawable.c b/shared-core/drm_drawable.c index d203b244..0817e321 100644 --- a/shared-core/drm_drawable.c +++ b/shared-core/drm_drawable.c @@ -43,7 +43,7 @@ int drm_adddraw(DRM_IOCTL_ARGS) { DRM_DEVICE; - unsigned int irqflags; + unsigned long irqflags; int i, j; u32 *bitfield = dev->drw_bitfield; unsigned int bitfield_length = dev->drw_bitfield_length; @@ -134,7 +134,7 @@ int drm_rmdraw(DRM_IOCTL_ARGS) drm_draw_t draw; int id, idx; unsigned int shift; - unsigned int irqflags; + unsigned long irqflags; u32 *bitfield = dev->drw_bitfield; unsigned int bitfield_length = dev->drw_bitfield_length; drm_drawable_info_t **info = dev->drw_info; @@ -220,9 +220,9 @@ int drm_rmdraw(DRM_IOCTL_ARGS) int drm_update_drawable_info(DRM_IOCTL_ARGS) { DRM_DEVICE; drm_update_draw_t update; - unsigned int id, idx, shift; + unsigned int id, idx, shift, bitfield_length = dev->drw_bitfield_length; u32 *bitfield = dev->drw_bitfield; - unsigned int irqflags, bitfield_length = dev->drw_bitfield_length; + unsigned long irqflags; drm_drawable_info_t *info; drm_clip_rect_t *rects; int err; diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 76c3a810..feb7acc7 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -45,7 +45,7 @@ static void i915_vblank_tasklet(drm_device_t *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned int irqflags; + unsigned long irqflags; struct list_head *list, *tmp; DRM_DEBUG("\n"); @@ -388,7 +388,8 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_vblank_swap_t swap; drm_i915_vbl_swap_t *vbl_swap; - unsigned int pipe, seqtype, irqflags, curseq; + unsigned int pipe, seqtype, curseq; + unsigned long irqflags; struct list_head *list; if (!dev_priv) { -- cgit v1.2.3 From d1b31a228b72b8dd8e588f0a0cc8eeabc3845f70 Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Sun, 16 Jul 2006 01:02:06 +0300 Subject: Bug 6209: [mach64] AGP DMA buffers not mapped correctly. Map the DMA buffers from the same linear address as the vertex bufs. If dev->agp_buffer_token is not set, mach64 drm maps the DMA buffers from linear address 0x0. --- shared-core/mach64_dma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core') diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 4c8edeab..36fddf0e 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -834,6 +834,7 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init) mach64_do_cleanup_dma(dev); return DRM_ERR(ENOMEM); } + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { -- cgit v1.2.3 From eea150e776657faca7d5b76aca75a33dc74fbc9d Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Sun, 16 Jul 2006 02:15:02 +0300 Subject: Bug 6242: [mach64] Use private DMA buffers, part #1. Factor out from mach64_freelist_get() the code to reclaim a completed buffer, this is to improve readability for me. --- shared-core/mach64_dma.c | 155 ++++++++++++++++++++++++----------------------- 1 file changed, 80 insertions(+), 75 deletions(-) (limited to 'shared-core') diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 36fddf0e..3f4394c0 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -1329,17 +1329,88 @@ int mach64_do_release_used_buffers(drm_mach64_private_t * dev_priv) return 0; } +static int mach64_do_reclaim_completed(drm_mach64_private_t * dev_priv) +{ + drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; + struct list_head *ptr; + struct list_head *tmp; + drm_mach64_freelist_t *entry; + u32 head, tail, ofs; + + mach64_ring_tick(dev_priv, ring); + head = ring->head; + tail = ring->tail; + + if (head == tail) { +#if MACH64_EXTRA_CHECKING + if (MACH64_READ(MACH64_GUI_STAT) & MACH64_GUI_ACTIVE) { + DRM_ERROR("Empty ring with non-idle engine!\n"); + mach64_dump_ring_info(dev_priv); + return -1; + } +#endif + /* last pass is complete, so release everything */ + mach64_do_release_used_buffers(dev_priv); + DRM_DEBUG("%s: idle engine, freed all buffers.\n", + __FUNCTION__); + if (list_empty(&dev_priv->free_list)) { + DRM_ERROR("Freelist empty with idle engine\n"); + return -1; + } + return 0; + } + /* Look for a completed buffer and bail out of the loop + * as soon as we find one -- don't waste time trying + * to free extra bufs here, leave that to do_release_used_buffers + */ + list_for_each_safe(ptr, tmp, &dev_priv->pending) { + entry = list_entry(ptr, drm_mach64_freelist_t, list); + ofs = entry->ring_ofs; + if (entry->discard && + ((head < tail && (ofs < head || ofs >= tail)) || + (head > tail && (ofs < head && ofs >= tail)))) { +#if MACH64_EXTRA_CHECKING + int i; + + for (i = head; i != tail; i = (i + 4) & ring->tail_mask) + { + u32 o1 = le32_to_cpu(((u32 *) ring-> + start)[i + 1]); + u32 o2 = GETBUFADDR(entry->buf); + + if (o1 == o2) { + DRM_ERROR + ("Attempting to free used buffer: " + "i=%d buf=0x%08x\n", + i, o1); + mach64_dump_ring_info(dev_priv); + return -1; + } + } +#endif + /* found a processed buffer */ + entry->buf->pending = 0; + list_del(ptr); + list_add_tail(ptr, &dev_priv->free_list); + DRM_DEBUG + ("%s: freed processed buffer (head=%d tail=%d " + "buf ring ofs=%d).\n", + __FUNCTION__, head, tail, ofs); + return 0; + } + } + + return 1; +} + drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv) { drm_mach64_descriptor_ring_t *ring = &dev_priv->ring; drm_mach64_freelist_t *entry; struct list_head *ptr; - struct list_head *tmp; int t; if (list_empty(&dev_priv->free_list)) { - u32 head, tail, ofs; - if (list_empty(&dev_priv->pending)) { DRM_ERROR ("Couldn't get buffer - pending and free lists empty\n"); @@ -1351,81 +1422,15 @@ drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv) return NULL; } - tail = ring->tail; for (t = 0; t < dev_priv->usec_timeout; t++) { - mach64_ring_tick(dev_priv, ring); - head = ring->head; + int ret; - if (head == tail) { -#if MACH64_EXTRA_CHECKING - if (MACH64_READ(MACH64_GUI_STAT) & - MACH64_GUI_ACTIVE) { - DRM_ERROR - ("Empty ring with non-idle engine!\n"); - mach64_dump_ring_info(dev_priv); - return NULL; - } -#endif - /* last pass is complete, so release everything */ - mach64_do_release_used_buffers(dev_priv); - DRM_DEBUG - ("%s: idle engine, freed all buffers.\n", - __FUNCTION__); - if (list_empty(&dev_priv->free_list)) { - DRM_ERROR - ("Freelist empty with idle engine\n"); - return NULL; - } + ret = mach64_do_reclaim_completed(dev_priv); + if (ret == 0) goto _freelist_entry_found; - } - /* Look for a completed buffer and bail out of the loop - * as soon as we find one -- don't waste time trying - * to free extra bufs here, leave that to do_release_used_buffers - */ - list_for_each_safe(ptr, tmp, &dev_priv->pending) { - entry = - list_entry(ptr, drm_mach64_freelist_t, - list); - ofs = entry->ring_ofs; - if (entry->discard && - ((head < tail - && (ofs < head || ofs >= tail)) - || (head > tail - && (ofs < head && ofs >= tail)))) { -#if MACH64_EXTRA_CHECKING - int i; - - for (i = head; i != tail; - i = (i + 4) & ring->tail_mask) { - u32 o1 = - le32_to_cpu(((u32 *) ring-> - start)[i + 1]); - u32 o2 = GETBUFADDR(entry->buf); - - if (o1 == o2) { - DRM_ERROR - ("Attempting to free used buffer: " - "i=%d buf=0x%08x\n", - i, o1); - mach64_dump_ring_info - (dev_priv); - return NULL; - } - } -#endif - /* found a processed buffer */ - entry->buf->pending = 0; - list_del(ptr); - entry->buf->used = 0; - list_add_tail(ptr, - &dev_priv->placeholders); - DRM_DEBUG - ("%s: freed processed buffer (head=%d tail=%d " - "buf ring ofs=%d).\n", - __FUNCTION__, head, tail, ofs); - return entry->buf; - } - } + if (ret < 0) + return NULL; + DRM_UDELAY(1); } mach64_dump_ring_info(dev_priv); -- cgit v1.2.3 From 25760c30d4aedb370423d0bb03c014cab47b5d4f Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Mon, 28 Aug 2006 05:44:37 +0300 Subject: Bug 6242: [mach64] Use private DMA buffers, part #2. Factor out from mach64_dma_dispatch_vertex() the code to reclaim an unsed buffer, in preperation for using it in mach64_dma_dispatch_blit() also. --- shared-core/mach64_dma.c | 27 ++++++++++ shared-core/mach64_drv.h | 2 + shared-core/mach64_state.c | 124 +++++++++++++++++++-------------------------- 3 files changed, 81 insertions(+), 72 deletions(-) (limited to 'shared-core') diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 3f4394c0..7cba8ade 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -1449,6 +1449,33 @@ drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv) return entry->buf; } +int mach64_freelist_put(drm_mach64_private_t * dev_priv, drm_buf_t * copy_buf) +{ + struct list_head *ptr; + drm_mach64_freelist_t *entry; + +#if MACH64_EXTRA_CHECKING + list_for_each(ptr, &dev_priv->pending) { + entry = list_entry(ptr, drm_mach64_freelist_t, list); + if (copy_buf == entry->buf) { + DRM_ERROR("%s: Trying to release a pending buf\n", + __FUNCTION__); + return DRM_ERR(EFAULT); + } + } +#endif + ptr = dev_priv->placeholders.next; + entry = list_entry(ptr, drm_mach64_freelist_t, list); + copy_buf->pending = 0; + copy_buf->used = 0; + entry->buf = copy_buf; + entry->discard = 1; + list_del(ptr); + list_add_tail(ptr, &dev_priv->free_list); + + return 0; +} + /*@}*/ diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h index 2a5f2ff9..e8dc71ef 100644 --- a/shared-core/mach64_drv.h +++ b/shared-core/mach64_drv.h @@ -123,6 +123,8 @@ extern void mach64_driver_lastclose(drm_device_t * dev); extern int mach64_init_freelist(drm_device_t * dev); extern void mach64_destroy_freelist(drm_device_t * dev); extern drm_buf_t *mach64_freelist_get(drm_mach64_private_t * dev_priv); +extern int mach64_freelist_put(drm_mach64_private_t * dev_priv, + drm_buf_t * copy_buf); extern int mach64_do_wait_for_fifo(drm_mach64_private_t * dev_priv, int entries); diff --git a/shared-core/mach64_state.c b/shared-core/mach64_state.c index ce44f0d5..31e3b563 100644 --- a/shared-core/mach64_state.c +++ b/shared-core/mach64_state.c @@ -546,12 +546,15 @@ static __inline__ int copy_and_verify_from_user(u32 *to, } static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev, - int prim, void *buf, unsigned long used, - int discard) + drm_mach64_vertex_t * vertex) { drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_buf_t *copy_buf; + void *buf = vertex->buf; + unsigned long used = vertex->used; + int ret = 0; + int i = 0; int done = 0; int verify_ret = 0; DMALOCALS; @@ -559,87 +562,65 @@ static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev, DRM_DEBUG("%s: buf=%p used=%lu nbox=%d\n", __FUNCTION__, buf, used, sarea_priv->nbox); - if (used) { - int ret = 0; - int i = 0; + if (!used) + goto _vertex_done; - copy_buf = mach64_freelist_get(dev_priv); - if (copy_buf == NULL) { - DRM_ERROR("%s: couldn't get buffer in DMAGETPTR\n", - __FUNCTION__); - return DRM_ERR(EAGAIN); - } + copy_buf = mach64_freelist_get(dev_priv); + if (copy_buf == NULL) { + DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__); + return DRM_ERR(EAGAIN); + } + + verify_ret = copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, used); - if ((verify_ret = - copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, - used)) == 0) { + if (verify_ret != 0) { + mach64_freelist_put(dev_priv, copy_buf); + goto _vertex_done; + } - copy_buf->used = used; + copy_buf->used = used; - DMASETPTR(copy_buf); + DMASETPTR(copy_buf); - if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { - ret = mach64_emit_state(filp, dev_priv); - if (ret < 0) - return ret; - } + if (sarea_priv->dirty & ~MACH64_UPLOAD_CLIPRECTS) { + ret = mach64_emit_state(filp, dev_priv); + if (ret < 0) + return ret; + } - do { - /* Emit the next cliprect */ - if (i < sarea_priv->nbox) { - ret = - mach64_emit_cliprect(filp, dev_priv, - &sarea_priv-> - boxes[i]); - if (ret < 0) { - /* failed to get buffer */ - return ret; - } else if (ret != 0) { - /* null intersection with scissor */ - continue; - } - } - if ((i >= sarea_priv->nbox - 1)) - done = 1; - - /* Add the buffer to the DMA queue */ - DMAADVANCE(dev_priv, done); - - } while (++i < sarea_priv->nbox); + do { + /* Emit the next cliprect */ + if (i < sarea_priv->nbox) { + ret = mach64_emit_cliprect(filp, dev_priv, + &sarea_priv->boxes[i]); + if (ret < 0) { + /* failed to get buffer */ + return ret; + } else if (ret != 0) { + /* null intersection with scissor */ + continue; + } } + if ((i >= sarea_priv->nbox - 1)) + done = 1; + + /* Add the buffer to the DMA queue */ + DMAADVANCE(dev_priv, done); + + } while (++i < sarea_priv->nbox); - if (copy_buf->pending && !done) { + if (!done) { + if (copy_buf->pending) { DMADISCARDBUF(); - } else if (!done) { - /* This buffer wasn't used (no cliprects or verify failed), so place it back - * on the free list + } else { + /* This buffer wasn't used (no cliprects), so place it + * back on the free list */ - struct list_head *ptr; - drm_mach64_freelist_t *entry; -#if MACH64_EXTRA_CHECKING - list_for_each(ptr, &dev_priv->pending) { - entry = - list_entry(ptr, drm_mach64_freelist_t, - list); - if (copy_buf == entry->buf) { - DRM_ERROR - ("%s: Trying to release a pending buf\n", - __FUNCTION__); - return DRM_ERR(EFAULT); - } - } -#endif - ptr = dev_priv->placeholders.next; - entry = list_entry(ptr, drm_mach64_freelist_t, list); - copy_buf->pending = 0; - copy_buf->used = 0; - entry->buf = copy_buf; - entry->discard = 1; - list_del(ptr); - list_add_tail(ptr, &dev_priv->free_list); + mach64_freelist_put(dev_priv, copy_buf); } } +_vertex_done: sarea_priv->dirty &= ~MACH64_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0; @@ -842,8 +823,7 @@ int mach64_dma_vertex(DRM_IOCTL_ARGS) if (sarea_priv->nbox > MACH64_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MACH64_NR_SAREA_CLIPRECTS; - return mach64_dma_dispatch_vertex(filp, dev, vertex.prim, vertex.buf, - vertex.used, vertex.discard); + return mach64_dma_dispatch_vertex(filp, dev, &vertex); } int mach64_dma_blit(DRM_IOCTL_ARGS) -- cgit v1.2.3 From f3deef730d52c94ce21ada7e4ceb63aa28a8601b Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Mon, 2 Oct 2006 05:46:42 +0300 Subject: Bug 6242: [mach64] Use private DMA buffers, part #3. Add DRM_PCI_BUFFER_RO flag for mapping PCI DMA buffer read-only. An additional flag is needed, since PCI DMA buffers do not have an associated map. --- shared-core/drm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 7f90a96d..8c0c5d22 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -416,7 +416,8 @@ typedef struct drm_buf_desc { _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ - _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */ + _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ + _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ } flags; unsigned long agp_start; /**< * Start address of where the AGP buffers are -- cgit v1.2.3 From c9e3aa961eb90265ec024ff57013786e4d47d0e7 Mon Sep 17 00:00:00 2001 From: George Sapountzis Date: Mon, 2 Oct 2006 06:13:38 +0300 Subject: Bug 6242: [mach64] Use private DMA buffers, part #4. mach64_state.c: convert the DRM_MACH64_BLIT ioctl to submit a pointer to user-space memory rather than a DMA buffer index, similar to DRM_MACH64_VERTEX. This change allows the DDX to map the DMA buffers read-only and eliminate a security problem where a client can alter the contents of the DMA buffer after submission to the DRM. This change also affects the DRI/DRM interface. Performace-wise, it basically affects PCI mode where I get a ~12% speedup for some Mesa demos I tested. This is mainly due to eliminating an ioctl for allocating the DMA buffer. mach64_dma.c: move the responsibility for allocating memory for the DMA ring in PCI mode to the DDX. This change affects the DDX/DRM interface and unifies a couple of PCI/AGP code paths for ring memory in the DRM. Bump the mach64 DRM version major and date. --- shared-core/mach64_dma.c | 51 +++++++++------------------- shared-core/mach64_drm.h | 2 +- shared-core/mach64_drv.h | 5 ++- shared-core/mach64_state.c | 83 ++++++++++++++++++++++++---------------------- 4 files changed, 62 insertions(+), 79 deletions(-) (limited to 'shared-core') diff --git a/shared-core/mach64_dma.c b/shared-core/mach64_dma.c index 7cba8ade..3a5fdee8 100644 --- a/shared-core/mach64_dma.c +++ b/shared-core/mach64_dma.c @@ -815,17 +815,18 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init) return DRM_ERR(EINVAL); } + dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset); + if (!dev_priv->ring_map) { + DRM_ERROR("can not find ring map!\n"); + dev->dev_private = (void *)dev_priv; + mach64_do_cleanup_dma(dev); + return DRM_ERR(EINVAL); + } + dev_priv->sarea_priv = (drm_mach64_sarea_t *) ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); if (!dev_priv->is_pci) { - dev_priv->ring_map = drm_core_findmap(dev, init->ring_offset); - if (!dev_priv->ring_map) { - DRM_ERROR("can not find ring map!\n"); - dev->dev_private = (void *)dev_priv; - mach64_do_cleanup_dma(dev); - return DRM_ERR(EINVAL); - } drm_core_ioremap(dev_priv->ring_map, dev); if (!dev_priv->ring_map->handle) { DRM_ERROR("can not ioremap virtual address for" @@ -891,27 +892,9 @@ static int mach64_do_dma_init(drm_device_t * dev, drm_mach64_init_t * init) } } - /* allocate descriptor memory from pci pool */ - DRM_DEBUG("Allocating dma descriptor ring\n"); dev_priv->ring.size = 0x4000; /* 16KB */ - - if (dev_priv->is_pci) { - dev_priv->ring.dmah = drm_pci_alloc(dev, dev_priv->ring.size, - dev_priv->ring.size, - 0xfffffffful); - - if (!dev_priv->ring.dmah) { - DRM_ERROR("Allocating dma descriptor ring failed\n"); - return DRM_ERR(ENOMEM); - } else { - dev_priv->ring.start = dev_priv->ring.dmah->vaddr; - dev_priv->ring.start_addr = - (u32) dev_priv->ring.dmah->busaddr; - } - } else { - dev_priv->ring.start = dev_priv->ring_map->handle; - dev_priv->ring.start_addr = (u32) dev_priv->ring_map->offset; - } + dev_priv->ring.start = dev_priv->ring_map->handle; + dev_priv->ring.start_addr = (u32) dev_priv->ring_map->offset; memset(dev_priv->ring.start, 0, dev_priv->ring.size); DRM_INFO("descriptor ring: cpu addr %p, bus addr: 0x%08x\n", @@ -1149,18 +1132,14 @@ int mach64_do_cleanup_dma(drm_device_t * dev) if (dev->dev_private) { drm_mach64_private_t *dev_priv = dev->dev_private; - if (dev_priv->is_pci) { - if (dev_priv->ring.dmah) { - drm_pci_free(dev, dev_priv->ring.dmah); - } - } else { + if (!dev_priv->is_pci) { if (dev_priv->ring_map) drm_core_ioremapfree(dev_priv->ring_map, dev); - } - if (dev->agp_buffer_map) { - drm_core_ioremapfree(dev->agp_buffer_map, dev); - dev->agp_buffer_map = NULL; + if (dev->agp_buffer_map) { + drm_core_ioremapfree(dev->agp_buffer_map, dev); + dev->agp_buffer_map = NULL; + } } mach64_destroy_freelist(dev); diff --git a/shared-core/mach64_drm.h b/shared-core/mach64_drm.h index 1fd8c002..083f959d 100644 --- a/shared-core/mach64_drm.h +++ b/shared-core/mach64_drm.h @@ -237,7 +237,7 @@ typedef struct drm_mach64_vertex { } drm_mach64_vertex_t; typedef struct drm_mach64_blit { - int idx; + void *buf; int pitch; int offset; int format; diff --git a/shared-core/mach64_drv.h b/shared-core/mach64_drv.h index e8dc71ef..bb8b309e 100644 --- a/shared-core/mach64_drv.h +++ b/shared-core/mach64_drv.h @@ -42,9 +42,9 @@ #define DRIVER_NAME "mach64" #define DRIVER_DESC "DRM module for the ATI Rage Pro" -#define DRIVER_DATE "20020904" +#define DRIVER_DATE "20060718" -#define DRIVER_MAJOR 1 +#define DRIVER_MAJOR 2 #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 @@ -61,7 +61,6 @@ typedef struct drm_mach64_freelist { } drm_mach64_freelist_t; typedef struct drm_mach64_descriptor_ring { - drm_dma_handle_t *dmah; /* Handle to pci dma memory */ void *start; /* write pointer (cpu address) to start of descriptor ring */ u32 start_addr; /* bus address of beginning of descriptor ring */ int size; /* size of ring in bytes */ diff --git a/shared-core/mach64_state.c b/shared-core/mach64_state.c index 31e3b563..38cefca9 100644 --- a/shared-core/mach64_state.c +++ b/shared-core/mach64_state.c @@ -480,16 +480,16 @@ static int mach64_do_get_frames_queued(drm_mach64_private_t * dev_priv) /* Copy and verify a client submited buffer. * FIXME: Make an assembly optimized version */ -static __inline__ int copy_and_verify_from_user(u32 *to, - const u32 __user *ufrom, - unsigned long bytes) +static __inline__ int copy_from_user_vertex(u32 *to, + const u32 __user *ufrom, + unsigned long bytes) { unsigned long n = bytes; /* dwords remaining in buffer */ u32 *from, *orig_from; from = drm_alloc(bytes, DRM_MEM_DRIVER); if (from == NULL) - return ENOMEM; + return DRM_ERR(ENOMEM); if (DRM_COPY_FROM_USER(from, ufrom, bytes)) { drm_free(from, bytes, DRM_MEM_DRIVER); @@ -571,7 +571,7 @@ static int mach64_dma_dispatch_vertex(DRMFILE filp, drm_device_t * dev, return DRM_ERR(EAGAIN); } - verify_ret = copy_and_verify_from_user(GETBUFPTR(copy_buf), buf, used); + verify_ret = copy_from_user_vertex(GETBUFPTR(copy_buf), buf, used); if (verify_ret != 0) { mach64_freelist_put(dev_priv, copy_buf); @@ -627,13 +627,27 @@ _vertex_done: return verify_ret; } +static __inline__ int copy_from_user_blit(u32 *to, + const u32 __user *ufrom, + unsigned long bytes) +{ + to = (u32 *)((char *)to + MACH64_HOSTDATA_BLIT_OFFSET); + + if (DRM_COPY_FROM_USER(to, ufrom, bytes)) { + return DRM_ERR(EFAULT); + } + + return 0; +} + static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, drm_mach64_blit_t * blit) { drm_mach64_private_t *dev_priv = dev->dev_private; - drm_device_dma_t *dma = dev->dma; int dword_shift, dwords; - drm_buf_t *buf; + unsigned long used; + drm_buf_t *copy_buf; + int verify_ret = 0; DMALOCALS; /* The compiler won't optimize away a division by a variable, @@ -660,34 +674,34 @@ static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, return DRM_ERR(EINVAL); } - /* Dispatch the blit buffer. - */ - buf = dma->buflist[blit->idx]; - - if (buf->filp != filp) { - DRM_ERROR("process %d (filp %p) using buffer with filp %p\n", - DRM_CURRENTPID, filp, buf->filp); - return DRM_ERR(EINVAL); - } - - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", blit->idx); - return DRM_ERR(EINVAL); - } - /* Set buf->used to the bytes of blit data based on the blit dimensions * and verify the size. When the setup is emitted to the buffer with * the DMA* macros below, buf->used is incremented to include the bytes * used for setup as well as the blit data. */ dwords = (blit->width * blit->height) >> dword_shift; - buf->used = dwords << 2; - if (buf->used <= 0 || - buf->used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { - DRM_ERROR("Invalid blit size: %d bytes\n", buf->used); + used = dwords << 2; + if (used <= 0 || + used > MACH64_BUFFER_SIZE - MACH64_HOSTDATA_BLIT_OFFSET) { + DRM_ERROR("Invalid blit size: %lu bytes\n", used); return DRM_ERR(EINVAL); } + copy_buf = mach64_freelist_get(dev_priv); + if (copy_buf == NULL) { + DRM_ERROR("%s: couldn't get buffer\n", __FUNCTION__); + return DRM_ERR(EAGAIN); + } + + verify_ret = copy_from_user_blit(GETBUFPTR(copy_buf), blit->buf, used); + + if (verify_ret != 0) { + mach64_freelist_put(dev_priv, copy_buf); + goto _blit_done; + } + + copy_buf->used = used; + /* FIXME: Use a last buffer flag and reduce the state emitted for subsequent, * continuation buffers? */ @@ -696,7 +710,7 @@ static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, * a register command every 16 dwords. State setup is added at the start of the * buffer -- the client leaves space for this based on MACH64_HOSTDATA_BLIT_OFFSET */ - DMASETPTR(buf); + DMASETPTR(copy_buf); DMAOUTREG(MACH64_Z_CNTL, 0); DMAOUTREG(MACH64_SCALE_3D_CNTL, 0); @@ -726,12 +740,13 @@ static int mach64_dma_dispatch_blit(DRMFILE filp, drm_device_t * dev, DMAOUTREG(MACH64_DST_X_Y, (blit->y << 16) | blit->x); DMAOUTREG(MACH64_DST_WIDTH_HEIGHT, (blit->height << 16) | blit->width); - DRM_DEBUG("%s: %d bytes\n", __FUNCTION__, buf->used); + DRM_DEBUG("%s: %lu bytes\n", __FUNCTION__, used); /* Add the buffer to the queue */ DMAADVANCEHOSTDATA(dev_priv); - return 0; +_blit_done: + return verify_ret; } /* ================================================================ @@ -829,7 +844,6 @@ int mach64_dma_vertex(DRM_IOCTL_ARGS) int mach64_dma_blit(DRM_IOCTL_ARGS) { DRM_DEVICE; - drm_device_dma_t *dma = dev->dma; drm_mach64_private_t *dev_priv = dev->dev_private; drm_mach64_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_mach64_blit_t blit; @@ -840,15 +854,6 @@ int mach64_dma_blit(DRM_IOCTL_ARGS) DRM_COPY_FROM_USER_IOCTL(blit, (drm_mach64_blit_t *) data, sizeof(blit)); - DRM_DEBUG("%s: pid=%d index=%d\n", - __FUNCTION__, DRM_CURRENTPID, blit.idx); - - if (blit.idx < 0 || blit.idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - blit.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); - } - ret = mach64_dma_dispatch_blit(filp, dev, &blit); /* Make sure we restore the 3D state next time. -- cgit v1.2.3 From a9f57a2b9c5897cbf568bf75342204b780566de0 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Tue, 10 Oct 2006 02:24:19 +0200 Subject: only allow specific type-3 packets to pass the verifier instead of all for r100/r200 as others might be unsafe (r300 already does this), and add checking for these we need but aren't safe. Check the RADEON_CP_INDX_BUFFER packet on both r200 and r300 as it isn't safe neither. --- shared-core/r300_cmdbuf.c | 33 +++++++++++++- shared-core/radeon_state.c | 109 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 138 insertions(+), 4 deletions(-) (limited to 'shared-core') diff --git a/shared-core/r300_cmdbuf.c b/shared-core/r300_cmdbuf.c index dc866823..c65ffd59 100644 --- a/shared-core/r300_cmdbuf.c +++ b/shared-core/r300_cmdbuf.c @@ -538,6 +538,36 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, return 0; } +static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + u32 *cmd = (u32 *) cmdbuf->buf; + int count, ret; + RING_LOCALS; + + count=(cmd[0]>>16) & 0x3fff; + + if ((cmd[1] & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); + return DRM_ERR(EINVAL); + } + ret = r300_check_offset(dev_priv, cmd[2]); + if (ret) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); + return DRM_ERR(EINVAL); + } + + BEGIN_RING(count+2); + OUT_RING(cmd[0]); + OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); + ADVANCE_RING(); + + cmdbuf->buf += (count+2)*4; + cmdbuf->bufsz -= (count+2)*4; + + return 0; +} + static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { @@ -578,10 +608,11 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, case RADEON_CNTL_BITBLT_MULTI: return r300_emit_bitblt_multi(dev_priv, cmdbuf); + case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ + return r300_emit_indx_buffer(dev_priv, cmdbuf); case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ - case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ case RADEON_WAIT_FOR_IDLE: case RADEON_CP_NOP: /* these packets are safe */ diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index b4478019..bf5e3d29 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -275,6 +275,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * unsigned int *cmdsz) { u32 *cmd = (u32 *) cmdbuf->buf; + u32 offset, narrays; + int count, i, k; *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); @@ -288,10 +290,106 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * return DRM_ERR(EINVAL); } - /* Check client state and fix it up if necessary */ - if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */ - u32 offset; + switch(cmd[0] & 0xff00) { + /* XXX Are there old drivers needing other packets? */ + case RADEON_3D_DRAW_IMMD: + case RADEON_3D_DRAW_VBUF: + case RADEON_3D_DRAW_INDX: + case RADEON_WAIT_FOR_IDLE: + case RADEON_CP_NOP: + case RADEON_3D_CLEAR_ZMASK: +/* case RADEON_CP_NEXT_CHAR: + case RADEON_CP_PLY_NEXTSCAN: + case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ + /* these packets are safe */ + break; + + case RADEON_CP_3D_DRAW_IMMD_2: + case RADEON_CP_3D_DRAW_VBUF_2: + case RADEON_CP_3D_DRAW_INDX_2: + case RADEON_3D_CLEAR_HIZ: + /* safe but r200 only */ + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_3D_LOAD_VBPNTR: + count = (cmd[0] >> 16) & 0x3fff; + + if (count > 18) { /* 12 arrays max */ + DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", + count); + return DRM_ERR(EINVAL); + } + + /* carefully check packet contents */ + narrays = cmd[1] & ~0xc000; + k = 0; + i = 2; + while ((k < narrays) && (i < (count + 2))) { + i++; /* skip attribute field */ + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { + DRM_ERROR + ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", + k, i); + return DRM_ERR(EINVAL); + } + k++; + i++; + if (k == narrays) + break; + /* have one more to process, they come in pairs */ + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { + DRM_ERROR + ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", + k, i); + return DRM_ERR(EINVAL); + } + k++; + i++; + } + /* do the counts match what we expect ? */ + if ((k != narrays) || (i != (count + 2))) { + DRM_ERROR + ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", + k, i, narrays, count + 1); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_3D_RNDR_GEN_INDX_PRIM: + if (dev_priv->microcode_version != UCODE_R100) { + DRM_ERROR("Invalid 3d packet for r200-class chip\n"); + return DRM_ERR(EINVAL); + } + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) { + DRM_ERROR("Invalid rndr_gen_indx offset\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CP_INDX_BUFFER: + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); + return DRM_ERR(EINVAL); + } + if ((cmd[1] & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); + return DRM_ERR(EINVAL); + } + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CNTL_HOSTDATA_BLT: + case RADEON_CNTL_PAINT_MULTI: + case RADEON_CNTL_BITBLT_MULTI: + /* MSB of opcode: next DWORD GUI_CNTL */ if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { offset = cmd[2] << 10; @@ -313,6 +411,11 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * } cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; } + break; + + default: + DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); + return DRM_ERR(EINVAL); } return 0; -- cgit v1.2.3