aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/agp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/agp')
-rw-r--r--drivers/char/agp/Kconfig89
-rw-r--r--drivers/char/agp/Makefile4
-rw-r--r--drivers/char/agp/agp.h139
-rw-r--r--drivers/char/agp/ali-agp.c75
-rw-r--r--drivers/char/agp/alpha-agp.c58
-rw-r--r--drivers/char/agp/amd-k7-agp.c133
-rw-r--r--drivers/char/agp/amd64-agp.c401
-rw-r--r--drivers/char/agp/ati-agp.c189
-rw-r--r--drivers/char/agp/backend.c86
-rw-r--r--drivers/char/agp/compat_ioctl.c287
-rw-r--r--drivers/char/agp/compat_ioctl.h106
-rw-r--r--drivers/char/agp/efficeon-agp.c103
-rw-r--r--drivers/char/agp/frontend.c121
-rw-r--r--drivers/char/agp/generic.c441
-rw-r--r--drivers/char/agp/hp-agp.c67
-rw-r--r--drivers/char/agp/i460-agp.c90
-rw-r--r--drivers/char/agp/intel-agp.c1292
-rw-r--r--drivers/char/agp/intel-agp.h193
-rw-r--r--drivers/char/agp/intel-gtt.c1446
-rw-r--r--drivers/char/agp/isoch.c57
-rw-r--r--drivers/char/agp/nvidia-agp.c116
-rw-r--r--drivers/char/agp/parisc-agp.c426
-rw-r--r--drivers/char/agp/sgi-agp.c54
-rw-r--r--drivers/char/agp/sis-agp.c362
-rw-r--r--drivers/char/agp/sworks-agp.c112
-rw-r--r--drivers/char/agp/uninorth-agp.c271
-rw-r--r--drivers/char/agp/via-agp.c82
27 files changed, 4404 insertions, 2396 deletions
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 486ed8a11b5..c528f96ee20 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -1,7 +1,7 @@
-config AGP
- tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU
- depends on ALPHA || IA64 || PPC || X86
- default y if GART_IOMMU
+menuconfig AGP
+ tristate "/dev/agpgart (AGP Support)"
+ depends on ALPHA || IA64 || PARISC || PPC || X86
+ depends on PCI
---help---
AGP (Accelerated Graphics Port) is a bus system mainly used to
connect graphics cards to the rest of the system.
@@ -15,116 +15,98 @@ config AGP
due to kernel allocation issues), you could use PCI accesses
and have up to a couple gigs of texture space.
- Note that this is the only means to have XFree4/GLX use
+ Note that this is the only means to have X/GLX use
write-combining with MTRR support on the AGP bus. Without it, OpenGL
direct rendering will be a lot slower but still faster than PIO.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
To compile this driver as a module, choose M here: the
module will be called agpgart.
+ You should say Y here if you want to use GLX or DRI.
+
+ If unsure, say N.
+
config AGP_ALI
tristate "ALI chipset support"
depends on AGP && X86_32
---help---
This option gives you AGP support for the GLX component of
- XFree86 4.x on the following ALi chipsets. The supported chipsets
+ X on the following ALi chipsets. The supported chipsets
include M1541, M1621, M1631, M1632, M1641,M1647,and M1651.
For the ALi-chipset question, ALi suggests you refer to
- <http://www.ali.com.tw/eng/support/index.shtml>.
+ <http://www.ali.com.tw/>.
The M1541 chipset can do AGP 1x and 2x, but note that there is an
acknowledged incompatibility with Matrox G200 cards. Due to
timing issues, this chipset cannot do AGP 2x with the G200.
This is a hardware limitation. AGP 1x seems to be fine, though.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
-
config AGP_ATI
tristate "ATI chipset support"
depends on AGP && X86_32
---help---
- This option gives you AGP support for the GLX component of
- XFree86 4.x on the ATI RadeonIGP family of chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ This option gives you AGP support for the GLX component of
+ X on the ATI RadeonIGP family of chipsets.
config AGP_AMD
tristate "AMD Irongate, 761, and 762 chipset support"
depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on AMD Irongate, 761, and 762 chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ X on AMD Irongate, 761, and 762 chipsets.
config AGP_AMD64
- tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU
- depends on AGP && X86
- default y if GART_IOMMU
+ tristate "AMD Opteron/Athlon64 on-CPU GART support"
+ depends on AGP && X86 && AMD_NB
help
This option gives you AGP support for the GLX component of
- XFree86 4.x using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
+ X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
You still need an external AGP bridge like the AMD 8151, VIA
K8T400M, SiS755. It may also support other AGP bridges when loaded
with agp_try_unsupported=1.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say Y
config AGP_INTEL
tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
depends on AGP && X86
+ select INTEL_GTT
help
- This option gives you AGP support for the GLX component of XFree86 4.x
+ This option gives you AGP support for the GLX component of X
on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
- E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G,
- 852GM, 855GM, 865G and I915 integrated graphics chipsets.
+ E7205 and E7505 chipsets and full support for the 810, 815, 830M,
+ 845G, 852GM, 855GM, 865G and I915 integrated graphics chipsets.
+
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI, or if you have any Intel integrated graphics
- chipsets. If unsure, say Y.
config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support"
depends on AGP && X86_32
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on the following NVIDIA chipsets. The supported chipsets
- include nForce and nForce2
+ X on NVIDIA chipsets including nForce and nForce2
config AGP_SIS
tristate "SiS chipset support"
- depends on AGP && X86_32
+ depends on AGP && X86
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on Silicon Integrated Systems [SiS] chipsets.
+ X on Silicon Integrated Systems [SiS] chipsets.
Note that 5591/5592 AGP chipsets are NOT supported.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
config AGP_SWORKS
tristate "Serverworks LE/HE chipset support"
depends on AGP && X86_32
help
- Say Y here to support the Serverworks AGP card. See
+ Say Y here to support the Serverworks AGP card. See
<http://www.serverworks.com/> for product descriptions and images.
config AGP_VIA
tristate "VIA chipset support"
- depends on AGP && X86_32
+ depends on AGP && X86
help
This option gives you AGP support for the GLX component of
- XFree86 4.x on VIA MVP3/Apollo Pro chipsets.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say N.
+ X on VIA MVP3/Apollo Pro chipsets.
config AGP_I460
tristate "Intel 460GX chipset support"
@@ -140,6 +122,14 @@ config AGP_HP_ZX1
This option gives you AGP GART support for the HP ZX1 chipset
for IA64 processors.
+config AGP_PARISC
+ tristate "HP Quicksilver AGP support"
+ depends on AGP && PARISC && 64BIT
+ help
+ This option gives you AGP GART support for the HP Quicksilver
+ AGP bus adapter on HP PA-RISC machines (Ok, just on the C8000
+ workstation...)
+
config AGP_ALPHA_CORE
tristate "Alpha AGP support"
depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL)
@@ -159,9 +149,6 @@ config AGP_EFFICEON
This option gives you AGP support for the Transmeta Efficeon
series processors with integrated northbridges.
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say Y.
-
config AGP_SGI_TIOCA
tristate "SGI TIO chipset AGP support"
depends on AGP && (IA64_SGI_SN2 || IA64_GENERIC)
@@ -169,3 +156,7 @@ config AGP_SGI_TIOCA
This option gives you AGP GART support for the SGI TIO chipset
for IA64 processors.
+config INTEL_GTT
+ tristate
+ depends on X86 && PCI
+
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
index d33a22f2fa0..604489bcdbf 100644
--- a/drivers/char/agp/Makefile
+++ b/drivers/char/agp/Makefile
@@ -1,5 +1,7 @@
agpgart-y := backend.o frontend.o generic.o isoch.o
+agpgart-$(CONFIG_COMPAT) += compat_ioctl.o
+
obj-$(CONFIG_AGP) += agpgart.o
obj-$(CONFIG_AGP_ALI) += ali-agp.o
obj-$(CONFIG_AGP_ATI) += ati-agp.o
@@ -8,8 +10,10 @@ obj-$(CONFIG_AGP_AMD64) += amd64-agp.o
obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o
obj-$(CONFIG_AGP_EFFICEON) += efficeon-agp.o
obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
+obj-$(CONFIG_AGP_PARISC) += parisc-agp.o
obj-$(CONFIG_AGP_I460) += i460-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-agp.o
+obj-$(CONFIG_INTEL_GTT) += intel-gtt.o
obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o
obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index b4af87c6f9c..b709749c863 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -19,9 +19,9 @@
* 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
- * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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.
*
*/
@@ -35,7 +35,7 @@
//#define AGP_DEBUG 1
#ifdef AGP_DEBUG
-#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __FUNCTION__ , ## y)
+#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __func__ , ## y)
#else
#define DBG(x,y...) do { } while (0)
#endif
@@ -53,11 +53,14 @@ enum aper_size_type {
struct gatt_mask {
unsigned long mask;
u32 type;
- /* totally device specific, for integrated chipsets that
+ /* totally device specific, for integrated chipsets that
* might have different types of memory masks. For other
* devices this will probably be ignored */
};
+#define AGP_PAGE_DESTROY_UNMAP 1
+#define AGP_PAGE_DESTROY_FREE 2
+
struct aper_size_info_8 {
int size;
int num_entries;
@@ -93,19 +96,18 @@ struct aper_size_info_fixed {
struct agp_bridge_driver {
struct module *owner;
- void *aperture_sizes;
+ const void *aperture_sizes;
int num_aperture_sizes;
enum aper_size_type size_type;
- int cant_use_aperture;
- int needs_scratch_page;
- struct gatt_mask *masks;
+ bool cant_use_aperture;
+ bool needs_scratch_page;
+ const struct gatt_mask *masks;
int (*fetch_size)(void);
int (*configure)(void);
void (*agp_enable)(struct agp_bridge_data *, u32);
void (*cleanup)(void);
void (*tlb_flush)(struct agp_memory *);
- unsigned long (*mask_memory)(struct agp_bridge_data *,
- unsigned long, int);
+ unsigned long (*mask_memory)(struct agp_bridge_data *, dma_addr_t, int);
void (*cache_flush)(void);
int (*create_gatt_table)(struct agp_bridge_data *);
int (*free_gatt_table)(struct agp_bridge_data *);
@@ -113,14 +115,17 @@ struct agp_bridge_driver {
int (*remove_memory)(struct agp_memory *, off_t, int);
struct agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type)(struct agp_memory *);
- void *(*agp_alloc_page)(struct agp_bridge_data *);
- void (*agp_destroy_page)(void *);
+ struct page *(*agp_alloc_page)(struct agp_bridge_data *);
+ int (*agp_alloc_pages)(struct agp_bridge_data *, struct agp_memory *, size_t);
+ void (*agp_destroy_page)(struct page *, int flags);
+ void (*agp_destroy_pages)(struct agp_memory *);
+ int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
};
struct agp_bridge_data {
- struct agp_version *version;
- struct agp_bridge_driver *driver;
- struct vm_operations_struct *vm_ops;
+ const struct agp_version *version;
+ const struct agp_bridge_driver *driver;
+ const struct vm_operations_struct *vm_ops;
void *previous_size;
void *current_size;
void *dev_private_data;
@@ -128,7 +133,8 @@ struct agp_bridge_data {
u32 __iomem *gatt_table;
u32 *gatt_table_real;
unsigned long scratch_page;
- unsigned long scratch_page_real;
+ struct page *scratch_page_page;
+ dma_addr_t scratch_page_dma;
unsigned long gart_bus_addr;
unsigned long gatt_bus_addr;
u32 mode;
@@ -144,6 +150,9 @@ struct agp_bridge_data {
char minor_version;
struct list_head list;
u32 apbase_config;
+ /* list of agp_memory mapped to the aperture */
+ struct list_head mapped_list;
+ spinlock_t mapped_lock;
};
#define KB(x) ((x) * 1024)
@@ -163,73 +172,6 @@ struct agp_bridge_data {
#define PGE_EMPTY(b, p) (!(p) || (p) == (unsigned long) (b)->scratch_page)
-/* Intel registers */
-#define INTEL_APSIZE 0xb4
-#define INTEL_ATTBASE 0xb8
-#define INTEL_AGPCTRL 0xb0
-#define INTEL_NBXCFG 0x50
-#define INTEL_ERRSTS 0x91
-
-/* Intel i830 registers */
-#define I830_GMCH_CTRL 0x52
-#define I830_GMCH_ENABLED 0x4
-#define I830_GMCH_MEM_MASK 0x1
-#define I830_GMCH_MEM_64M 0x1
-#define I830_GMCH_MEM_128M 0
-#define I830_GMCH_GMS_MASK 0x70
-#define I830_GMCH_GMS_DISABLED 0x00
-#define I830_GMCH_GMS_LOCAL 0x10
-#define I830_GMCH_GMS_STOLEN_512 0x20
-#define I830_GMCH_GMS_STOLEN_1024 0x30
-#define I830_GMCH_GMS_STOLEN_8192 0x40
-#define I830_RDRAM_CHANNEL_TYPE 0x03010
-#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5)
-#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3)
-
-/* This one is for I830MP w. an external graphic card */
-#define INTEL_I830_ERRSTS 0x92
-
-/* Intel 855GM/852GM registers */
-#define I855_GMCH_GMS_STOLEN_0M 0x0
-#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
-#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
-#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4)
-#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4)
-#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4)
-#define I85X_CAPID 0x44
-#define I85X_VARIANT_MASK 0x7
-#define I85X_VARIANT_SHIFT 5
-#define I855_GME 0x0
-#define I855_GM 0x4
-#define I852_GME 0x2
-#define I852_GM 0x5
-
-/* Intel i845 registers */
-#define INTEL_I845_AGPM 0x51
-#define INTEL_I845_ERRSTS 0xc8
-
-/* Intel i860 registers */
-#define INTEL_I860_MCHCFG 0x50
-#define INTEL_I860_ERRSTS 0xc8
-
-/* Intel i810 registers */
-#define I810_GMADDR 0x10
-#define I810_MMADDR 0x14
-#define I810_PTE_BASE 0x10000
-#define I810_PTE_MAIN_UNCACHED 0x00000000
-#define I810_PTE_LOCAL 0x00000002
-#define I810_PTE_VALID 0x00000001
-#define I810_SMRAM_MISCC 0x70
-#define I810_GFX_MEM_WIN_SIZE 0x00010000
-#define I810_GFX_MEM_WIN_32M 0x00010000
-#define I810_GMS 0x000000c0
-#define I810_GMS_DISABLE 0x00000000
-#define I810_PGETBL_CTL 0x2020
-#define I810_PGETBL_ENABLED 0x00000001
-#define I810_DRAM_CTL 0x3000
-#define I810_DRAM_ROW_0 0x00000001
-#define I810_DRAM_ROW_0_SDRAM 0x00000001
-
struct agp_device_ids {
unsigned short device_id; /* first, to make table easier to read */
enum chipset_type chipset;
@@ -256,19 +198,30 @@ int agp_generic_insert_memory(struct agp_memory *mem, off_t pg_start, int type);
int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
void agp_generic_free_by_type(struct agp_memory *curr);
-void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
-void agp_generic_destroy_page(void *addr);
+struct page *agp_generic_alloc_page(struct agp_bridge_data *bridge);
+int agp_generic_alloc_pages(struct agp_bridge_data *agp_bridge,
+ struct agp_memory *memory, size_t page_count);
+void agp_generic_destroy_page(struct page *page, int flags);
+void agp_generic_destroy_pages(struct agp_memory *memory);
void agp_free_key(int key);
int agp_num_entries(void);
u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
-void agp_device_command(u32 command, int agp_v3);
+void agp_device_command(u32 command, bool agp_v3);
int agp_3_5_enable(struct agp_bridge_data *bridge);
void global_cache_flush(void);
void get_agp_version(struct agp_bridge_data *bridge);
unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
- unsigned long addr, int type);
+ dma_addr_t phys, int type);
+int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
+ int type);
struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
+/* generic functions for user-populated AGP memory types */
+struct agp_memory *agp_generic_alloc_user(size_t page_count, int type);
+void agp_alloc_page_array(size_t size, struct agp_memory *mem);
+void agp_free_page_array(struct agp_memory *mem);
+
+
/* generic routines for agp>=3 */
int agp3_generic_fetch_size(void);
void agp3_generic_tlbflush(struct agp_memory *mem);
@@ -277,16 +230,16 @@ void agp3_generic_cleanup(void);
/* aperture sizes have been standardised since v3 */
#define AGP_GENERIC_SIZES_ENTRIES 11
-extern struct aper_size_info_16 agp3_generic_sizes[];
-
-#define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
-#define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
+extern const struct aper_size_info_16 agp3_generic_sizes[];
extern int agp_off;
extern int agp_try_unsupported_boot;
-/* Chipset independant registers (from AGP Spec) */
+long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
+/* Chipset independent registers (from AGP Spec) */
#define AGP_APBASE 0x10
+#define AGP_APERTURE_BAR 0
#define AGPSTAT 0x4
#define AGPCMD 0x8
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index b02fc226715..19db0366765 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -85,8 +85,8 @@ static int ali_configure(void)
pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, ((temp & 0xffffff00) | 0x00000010));
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
#if 0
if (agp_bridge->type == ALI_M1541) {
@@ -110,7 +110,8 @@ static int ali_configure(void)
nlvm_addr+= agp_bridge->gart_bus_addr;
nlvm_addr|=(agp_bridge->gart_bus_addr>>12);
- printk(KERN_INFO PFX "nlvm top &base = %8x\n",nlvm_addr);
+ dev_info(&agp_bridge->dev->dev, "nlvm top &base = %8x\n",
+ nlvm_addr);
}
#endif
@@ -140,49 +141,54 @@ static void m1541_cache_flush(void)
}
}
-static void *m1541_alloc_page(struct agp_bridge_data *bridge)
+static struct page *m1541_alloc_page(struct agp_bridge_data *bridge)
{
- void *addr = agp_generic_alloc_page(agp_bridge);
+ struct page *page = agp_generic_alloc_page(agp_bridge);
u32 temp;
- if (!addr)
+ if (!page)
return NULL;
-
+
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN ));
- return addr;
+ page_to_phys(page)) | ALI_CACHE_FLUSH_EN ));
+ return page;
}
-static void ali_destroy_page(void * addr)
+static void ali_destroy_page(struct page *page, int flags)
{
- if (addr) {
- global_cache_flush(); /* is this really needed? --hch */
- agp_generic_destroy_page(addr);
+ if (page) {
+ if (flags & AGP_PAGE_DESTROY_UNMAP) {
+ global_cache_flush(); /* is this really needed? --hch */
+ agp_generic_destroy_page(page, flags);
+ } else
+ agp_generic_destroy_page(page, flags);
}
}
-static void m1541_destroy_page(void * addr)
+static void m1541_destroy_page(struct page *page, int flags)
{
u32 temp;
- if (addr == NULL)
+ if (page == NULL)
return;
- global_cache_flush();
+ if (flags & AGP_PAGE_DESTROY_UNMAP) {
+ global_cache_flush();
- pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
- pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
- (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
- agp_generic_destroy_page(addr);
+ pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
+ pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
+ (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+ page_to_phys(page)) | ALI_CACHE_FLUSH_EN));
+ }
+ agp_generic_destroy_page(page, flags);
}
/* Setup function */
-static struct aper_size_info_32 ali_generic_sizes[7] =
+static const struct aper_size_info_32 ali_generic_sizes[7] =
{
{256, 65536, 6, 10},
{128, 32768, 5, 9},
@@ -193,11 +199,12 @@ static struct aper_size_info_32 ali_generic_sizes[7] =
{4, 1024, 0, 3}
};
-static struct agp_bridge_driver ali_generic_bridge = {
+static const struct agp_bridge_driver ali_generic_bridge = {
.owner = THIS_MODULE,
.aperture_sizes = ali_generic_sizes,
.size_type = U32_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = ali_configure,
.fetch_size = ali_fetch_size,
.cleanup = ali_cleanup,
@@ -214,9 +221,10 @@ static struct agp_bridge_driver ali_generic_bridge = {
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
.agp_destroy_page = ali_destroy_page,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver ali_m1541_bridge = {
+static const struct agp_bridge_driver ali_m1541_bridge = {
.owner = THIS_MODULE,
.aperture_sizes = ali_generic_sizes,
.size_type = U32_APER_SIZE,
@@ -237,10 +245,11 @@ static struct agp_bridge_driver ali_m1541_bridge = {
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = m1541_alloc_page,
.agp_destroy_page = m1541_destroy_page,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_device_ids ali_agp_device_ids[] __devinitdata =
+static struct agp_device_ids ali_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_AL_M1541,
@@ -290,8 +299,7 @@ static struct agp_device_ids ali_agp_device_ids[] __devinitdata =
{ }, /* dummy final entry, always present */
};
-static int __devinit agp_ali_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_ali_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct agp_device_ids *devs = ali_agp_device_ids;
struct agp_bridge_data *bridge;
@@ -308,8 +316,8 @@ static int __devinit agp_ali_probe(struct pci_dev *pdev,
goto found;
}
- printk(KERN_ERR PFX "Unsupported ALi chipset (device id: %04x)\n",
- pdev->device);
+ dev_err(&pdev->dev, "unsupported ALi chipset [%04x/%04x])\n",
+ pdev->vendor, pdev->device);
return -ENODEV;
@@ -338,7 +346,7 @@ found:
devs[j].chipset_name = "M1641";
break;
case 0x43:
- devs[j].chipset_name = "M????";
+ devs[j].chipset_name = "M1621";
break;
case 0x47:
devs[j].chipset_name = "M1647";
@@ -354,8 +362,7 @@ found:
bridge->driver = &ali_generic_bridge;
}
- printk(KERN_INFO PFX "Detected ALi %s chipset\n",
- devs[j].chipset_name);
+ dev_info(&pdev->dev, "ALi %s chipset\n", devs[j].chipset_name);
/* Fill in the mode register */
pci_read_config_dword(pdev,
@@ -366,7 +373,7 @@ found:
return agp_add_bridge(bridge);
}
-static void __devexit agp_ali_remove(struct pci_dev *pdev)
+static void agp_ali_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -410,6 +417,6 @@ static void __exit agp_ali_cleanup(void)
module_init(agp_ali_init);
module_exit(agp_ali_cleanup);
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index a072d32005a..199b8e99f7d 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -11,28 +11,28 @@
#include "agp.h"
-static struct page *alpha_core_agp_vm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type)
+static int alpha_core_agp_vm_fault(struct vm_area_struct *vma,
+ struct vm_fault *vmf)
{
alpha_agp_info *agp = agp_bridge->dev_private_data;
dma_addr_t dma_addr;
unsigned long pa;
struct page *page;
- dma_addr = address - vma->vm_start + agp->aperture.bus_base;
+ dma_addr = (unsigned long)vmf->virtual_address - vma->vm_start
+ + agp->aperture.bus_base;
pa = agp->ops->translate(agp, dma_addr);
- if (pa == (unsigned long)-EINVAL) return NULL; /* no translation */
-
+ if (pa == (unsigned long)-EINVAL)
+ return VM_FAULT_SIGBUS; /* no translation */
+
/*
* Get the page, inc the use count, and return it
*/
page = virt_to_page(__va(pa));
get_page(page);
- if (type)
- *type = VM_FAULT_MINOR;
- return page;
+ vmf->page = page;
+ return 0;
}
static struct aper_size_info_fixed alpha_core_agp_sizes[] =
@@ -40,17 +40,11 @@ static struct aper_size_info_fixed alpha_core_agp_sizes[] =
{ 0, 0, 0 }, /* filled in by alpha_core_agp_setup */
};
-struct vm_operations_struct alpha_core_agp_vm_ops = {
- .nopage = alpha_core_agp_vm_nopage,
+static const struct vm_operations_struct alpha_core_agp_vm_ops = {
+ .fault = alpha_core_agp_vm_fault,
};
-static int alpha_core_agp_nop(void)
-{
- /* just return success */
- return 0;
-}
-
static int alpha_core_agp_fetch_size(void)
{
return alpha_core_agp_sizes[0].size;
@@ -86,19 +80,23 @@ static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode)
agp->mode.bits.enable = 1;
agp->ops->configure(agp);
- agp_device_command(agp->mode.lw, 0);
+ agp_device_command(agp->mode.lw, false);
}
-static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
+static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
int type)
{
alpha_agp_info *agp = agp_bridge->dev_private_data;
int num_entries, status;
void *temp;
+ if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+ return -EINVAL;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
- if ((pg_start + mem->page_count) > num_entries) return -EINVAL;
+ if ((pg_start + mem->page_count) > num_entries)
+ return -EINVAL;
status = agp->ops->bind(agp, pg_start, mem);
mb();
@@ -107,7 +105,7 @@ static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
return status;
}
-static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
+static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
int type)
{
alpha_agp_info *agp = agp_bridge->dev_private_data;
@@ -118,14 +116,19 @@ static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
return status;
}
+static int alpha_core_agp_create_free_gatt_table(struct agp_bridge_data *a)
+{
+ return 0;
+}
+
struct agp_bridge_driver alpha_core_agp_driver = {
.owner = THIS_MODULE,
.aperture_sizes = alpha_core_agp_sizes,
.num_aperture_sizes = 1,
.size_type = FIXED_APER_SIZE,
- .cant_use_aperture = 1,
+ .cant_use_aperture = true,
.masks = NULL,
-
+
.fetch_size = alpha_core_agp_fetch_size,
.configure = alpha_core_agp_configure,
.agp_enable = alpha_core_agp_enable,
@@ -133,14 +136,17 @@ struct agp_bridge_driver alpha_core_agp_driver = {
.tlb_flush = alpha_core_agp_tlbflush,
.mask_memory = agp_generic_mask_memory,
.cache_flush = global_cache_flush,
- .create_gatt_table = alpha_core_agp_nop,
- .free_gatt_table = alpha_core_agp_nop,
+ .create_gatt_table = alpha_core_agp_create_free_gatt_table,
+ .free_gatt_table = alpha_core_agp_create_free_gatt_table,
.insert_memory = alpha_core_agp_insert_memory,
.remove_memory = alpha_core_agp_remove_memory,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
struct agp_bridge_data *alpha_bridge;
@@ -168,7 +174,7 @@ alpha_core_agp_setup(void)
/*
* Build a fake pci_dev struct
*/
- pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+ pdev = pci_alloc_dev(NULL);
if (!pdev)
return -ENOMEM;
pdev->vendor = 0xffff;
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 1f776651ac6..3661a51e93e 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -6,12 +6,12 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
-#include <linux/gfp.h>
#include <linux/page-flags.h>
#include <linux/mm.h>
+#include <linux/slab.h>
#include "agp.h"
-#define AMD_MMBASE 0x14
+#define AMD_MMBASE_BAR 1
#define AMD_APSIZE 0xac
#define AMD_MODECNTL 0xb0
#define AMD_MODECNTL2 0xb2
@@ -41,17 +41,8 @@ static int amd_create_page_map(struct amd_page_map *page_map)
if (page_map->real == NULL)
return -ENOMEM;
- SetPageReserved(virt_to_page(page_map->real));
- global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
- PAGE_SIZE);
- if (page_map->remapped == NULL) {
- ClearPageReserved(virt_to_page(page_map->real));
- free_page((unsigned long) page_map->real);
- page_map->real = NULL;
- return -ENOMEM;
- }
- global_cache_flush();
+ set_memory_uc((unsigned long)page_map->real, 1);
+ page_map->remapped = page_map->real;
for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
writel(agp_bridge->scratch_page, page_map->remapped+i);
@@ -63,8 +54,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
static void amd_free_page_map(struct amd_page_map *page_map)
{
- iounmap(page_map->remapped);
- ClearPageReserved(virt_to_page(page_map->real));
+ set_memory_wb((unsigned long)page_map->real, 1);
free_page((unsigned long) page_map->real);
}
@@ -100,16 +90,16 @@ static int amd_create_gatt_pages(int nr_tables)
for (i = 0; i < nr_tables; i++) {
entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL);
+ tables[i] = entry;
if (entry == NULL) {
retval = -ENOMEM;
break;
}
- tables[i] = entry;
retval = amd_create_page_map(entry);
if (retval != 0)
break;
}
- amd_irongate_private.num_tables = nr_tables;
+ amd_irongate_private.num_tables = i;
amd_irongate_private.gatt_pages = tables;
if (retval != 0)
@@ -118,7 +108,7 @@ static int amd_create_gatt_pages(int nr_tables)
return retval;
}
-/* Since we don't need contigious memory we just try
+/* Since we don't need contiguous memory we just try
* to get the gatt table once
*/
@@ -133,9 +123,9 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
{
struct aper_size_info_lvl2 *value;
struct amd_page_map page_dir;
+ unsigned long __iomem *cur_gatt;
unsigned long addr;
int retval;
- u32 temp;
int i;
value = A_SIZE_LVL2(agp_bridge->current_size);
@@ -151,24 +141,30 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
* used to program the agp master not the cpu
*/
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
agp_bridge->gart_bus_addr = addr;
/* Calculate the agp offset */
for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
+ writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
+ for (i = 0; i < value->num_entries; i++) {
+ addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
+ cur_gatt = GET_GATT(addr);
+ writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
+ readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
+ }
+
return 0;
}
@@ -209,15 +205,19 @@ static int amd_irongate_fetch_size(void)
static int amd_irongate_configure(void)
{
struct aper_size_info_lvl2 *current_size;
+ phys_addr_t reg;
u32 temp;
u16 enable_reg;
current_size = A_SIZE_LVL2(agp_bridge->current_size);
- /* Get the memory mapped registers */
- pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
- temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+ if (!amd_irongate_private.registers) {
+ /* Get the memory mapped registers */
+ reg = pci_resource_start(agp_bridge->dev, AMD_MMBASE_BAR);
+ amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(reg, 4096);
+ if (!amd_irongate_private.registers)
+ return -ENOMEM;
+ }
/* Write out the address of the gatt table */
writel(agp_bridge->gatt_bus_addr, amd_irongate_private.registers+AMD_ATTBASE);
@@ -270,7 +270,7 @@ static void amd_irongate_cleanup(void)
* This routine could be implemented by taking the addresses
* written to the GATT, and flushing them individually. However
* currently it just flushes the whole table. Which is probably
- * more efficent, since agp_memory blocks can be a large number of
+ * more efficient, since agp_memory blocks can be a large number of
* entries.
*/
@@ -288,7 +288,8 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
- if (type != 0 || mem->type != 0)
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type))
return -EINVAL;
if ((pg_start + mem->page_count) > num_entries)
@@ -303,16 +304,18 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
j++;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
global_cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
writel(agp_generic_mask_memory(agp_bridge,
- mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+ page_to_phys(mem->pages[i]),
+ mem->type),
+ cur_gatt+GET_GATT_OFF(addr));
readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
}
amd_irongate_tlbflush(mem);
@@ -325,7 +328,8 @@ static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
unsigned long __iomem *cur_gatt;
unsigned long addr;
- if (type != 0 || mem->type != 0)
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type))
return -EINVAL;
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
@@ -339,7 +343,7 @@ static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
return 0;
}
-static struct aper_size_info_lvl2 amd_irongate_sizes[7] =
+static const struct aper_size_info_lvl2 amd_irongate_sizes[7] =
{
{2048, 524288, 0x0000000c},
{1024, 262144, 0x0000000a},
@@ -350,16 +354,17 @@ static struct aper_size_info_lvl2 amd_irongate_sizes[7] =
{32, 8192, 0x00000000}
};
-static struct gatt_mask amd_irongate_masks[] =
+static const struct gatt_mask amd_irongate_masks[] =
{
{.mask = 1, .type = 0}
};
-static struct agp_bridge_driver amd_irongate_driver = {
+static const struct agp_bridge_driver amd_irongate_driver = {
.owner = THIS_MODULE,
.aperture_sizes = amd_irongate_sizes,
.size_type = LVL2_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = amd_irongate_configure,
.fetch_size = amd_irongate_fetch_size,
.cleanup = amd_irongate_cleanup,
@@ -375,10 +380,13 @@ static struct agp_bridge_driver amd_irongate_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
+static struct agp_device_ids amd_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006,
@@ -395,8 +403,8 @@ static struct agp_device_ids amd_agp_device_ids[] __devinitdata =
{ }, /* dummy final entry, always present */
};
-static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_amdk7_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
u8 cap_ptr;
@@ -407,8 +415,8 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
return -ENODEV;
j = ent - agp_amdk7_pci_table;
- printk(KERN_INFO PFX "Detected AMD %s chipset\n",
- amd_agp_device_ids[j].chipset_name);
+ dev_info(&pdev->dev, "AMD %s chipset\n",
+ amd_agp_device_ids[j].chipset_name);
bridge = agp_alloc_bridge();
if (!bridge)
@@ -424,19 +432,16 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
system controller may experience noise due to strong drive strengths
*/
if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
- u8 cap_ptr=0;
struct pci_dev *gfxcard=NULL;
+
+ cap_ptr = 0;
while (!cap_ptr) {
gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
if (!gfxcard) {
- printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+ dev_info(&pdev->dev, "no AGP VGA controller\n");
return -ENODEV;
}
cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP);
- if (!cap_ptr) {
- pci_dev_put(gfxcard);
- continue;
- }
}
/* With so many variants of NVidia cards, it's simpler just
@@ -444,7 +449,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
(if necessary at all). */
if (gfxcard->vendor == PCI_VENDOR_ID_NVIDIA) {
agp_bridge->flags |= AGP_ERRATA_1X;
- printk (KERN_INFO PFX "AMD 751 chipset with NVidia GeForce detected. Forcing to 1X due to errata.\n");
+ dev_info(&pdev->dev, "AMD 751 chipset with NVidia GeForce; forcing 1X due to errata\n");
}
pci_dev_put(gfxcard);
}
@@ -456,13 +461,11 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
* erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
* With this lot disabled, we should prevent lockups. */
if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
- u8 revision=0;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
- if (revision == 0x10 || revision == 0x11) {
+ if (pdev->revision == 0x10 || pdev->revision == 0x11) {
agp_bridge->flags = AGP_ERRATA_FASTWRITES;
agp_bridge->flags |= AGP_ERRATA_SBA;
agp_bridge->flags |= AGP_ERRATA_1X;
- printk (KERN_INFO PFX "AMD 761 chipset with errata detected - disabling AGP fast writes & SBA and forcing to 1X.\n");
+ dev_info(&pdev->dev, "AMD 761 chipset with errata; disabling AGP fast writes & SBA and forcing to 1X\n");
}
}
@@ -475,7 +478,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
+static void agp_amdk7_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -483,6 +486,26 @@ static void __devexit agp_amdk7_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
+#ifdef CONFIG_PM
+
+static int agp_amdk7_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int agp_amdk7_resume(struct pci_dev *pdev)
+{
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ return amd_irongate_driver.configure();
+}
+
+#endif /* CONFIG_PM */
+
/* must be the same order as name table above */
static struct pci_device_id agp_amdk7_pci_table[] = {
{
@@ -519,6 +542,10 @@ static struct pci_driver agp_amdk7_pci_driver = {
.id_table = agp_amdk7_pci_table,
.probe = agp_amdk7_probe,
.remove = agp_amdk7_remove,
+#ifdef CONFIG_PM
+ .suspend = agp_amdk7_suspend,
+ .resume = agp_amdk7_resume,
+#endif
};
static int __init agp_amdk7_init(void)
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 9964c508c11..3b47ed0310e 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -8,38 +8,17 @@
* work is done in the northbridge(s).
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
#include <linux/mmzone.h>
#include <asm/page.h> /* PAGE_SIZE */
+#include <asm/e820.h>
+#include <asm/amd_nb.h>
+#include <asm/gart.h>
#include "agp.h"
-/* Will need to be increased if AMD64 ever goes >8-way. */
-#define MAX_HAMMER_GARTS 8
-
-/* PTE bits. */
-#define GPTE_VALID 1
-#define GPTE_COHERENT 2
-
-/* Aperture control register bits. */
-#define GARTEN (1<<0)
-#define DISGARTCPU (1<<4)
-#define DISGARTIO (1<<5)
-
-/* GART cache control register bits. */
-#define INVGART (1<<0)
-#define GARTPTEERR (1<<1)
-
-/* K8 On-cpu GART registers */
-#define AMD64_GARTAPERTURECTL 0x90
-#define AMD64_GARTAPERTUREBASE 0x94
-#define AMD64_GARTTABLEBASE 0x98
-#define AMD64_GARTCACHECTL 0x9c
-#define AMD64_GARTEN (1<<0)
-
/* NVIDIA K8 registers */
#define NVIDIA_X86_64_0_APBASE 0x10
#define NVIDIA_X86_64_1_APBASE1 0x50
@@ -53,41 +32,32 @@
#define ULI_X86_64_HTT_FEA_REG 0x50
#define ULI_X86_64_ENU_SCR_REG 0x54
-static int nr_garts;
-static struct pci_dev * hammers[MAX_HAMMER_GARTS];
-
static struct resource *aperture_resource;
-static int __initdata agp_try_unsupported = 1;
-
-#define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++)
-
-static void flush_amd64_tlb(struct pci_dev *dev)
-{
- u32 tmp;
-
- pci_read_config_dword (dev, AMD64_GARTCACHECTL, &tmp);
- tmp |= INVGART;
- pci_write_config_dword (dev, AMD64_GARTCACHECTL, tmp);
-}
+static bool __initdata agp_try_unsupported = 1;
+static int agp_bridges_found;
static void amd64_tlbflush(struct agp_memory *temp)
{
- int gart_iterator;
- for_each_nb()
- flush_amd64_tlb(hammers[gart_iterator]);
+ amd_flush_garts();
}
static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
{
int i, j, num_entries;
long long tmp;
+ int mask_type;
+ struct agp_bridge_data *bridge = mem->bridge;
u32 pte;
num_entries = agp_num_entries();
- if (type != 0 || mem->type != 0)
+ if (type != mem->type)
+ return -EINVAL;
+ mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+ if (mask_type != 0)
return -EINVAL;
+
/* Make sure we can fit the range in the gatt table. */
/* FIXME: could wrap */
if (((unsigned long)pg_start + mem->page_count) > num_entries)
@@ -102,14 +72,15 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
j++;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
global_cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
tmp = agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mem->type);
+ page_to_phys(mem->pages[i]),
+ mask_type);
BUG_ON(tmp & 0xffffff0000000ffcULL);
pte = (tmp & 0x000000ff00000000ULL) >> 28;
@@ -153,7 +124,7 @@ static int amd64_fetch_size(void)
u32 temp;
struct aper_size_info_32 *values;
- dev = hammers[0];
+ dev = node_to_amd_nb(0)->misc;
if (dev==NULL)
return 0;
@@ -177,38 +148,24 @@ static int amd64_fetch_size(void)
* In a multiprocessor x86-64 system, this function gets
* called once for each CPU.
*/
-static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table)
+static u64 amd64_configure(struct pci_dev *hammer, u64 gatt_table)
{
u64 aperturebase;
u32 tmp;
- u64 addr, aper_base;
+ u64 aper_base;
/* Address to map to */
- pci_read_config_dword (hammer, AMD64_GARTAPERTUREBASE, &tmp);
+ pci_read_config_dword(hammer, AMD64_GARTAPERTUREBASE, &tmp);
aperturebase = tmp << 25;
aper_base = (aperturebase & PCI_BASE_ADDRESS_MEM_MASK);
- /* address of the mappings table */
- addr = (u64) gatt_table;
- addr >>= 12;
- tmp = (u32) addr<<4;
- tmp &= ~0xf;
- pci_write_config_dword (hammer, AMD64_GARTTABLEBASE, tmp);
-
- /* Enable GART translation for this hammer. */
- pci_read_config_dword(hammer, AMD64_GARTAPERTURECTL, &tmp);
- tmp |= GARTEN;
- tmp &= ~(DISGARTCPU | DISGARTIO);
- pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp);
-
- /* keep CPU's coherent. */
- flush_amd64_tlb (hammer);
+ enable_gart_translation(hammer, gatt_table);
return aper_base;
}
-static struct aper_size_info_32 amd_8151_sizes[7] =
+static const struct aper_size_info_32 amd_8151_sizes[7] =
{
{2048, 524288, 9, 0x00000000 }, /* 0 0 0 0 0 0 */
{1024, 262144, 8, 0x00000400 }, /* 1 0 0 0 0 0 */
@@ -216,19 +173,23 @@ static struct aper_size_info_32 amd_8151_sizes[7] =
{256, 65536, 6, 0x00000700 }, /* 1 1 1 0 0 0 */
{128, 32768, 5, 0x00000720 }, /* 1 1 1 1 0 0 */
{64, 16384, 4, 0x00000730 }, /* 1 1 1 1 1 0 */
- {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */
+ {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */
};
static int amd_8151_configure(void)
{
- unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
- int gart_iterator;
+ unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+ int i;
+
+ if (!amd_nb_has_feature(AMD_NB_GART))
+ return 0;
/* Configure AGP regs in each x86-64 host bridge. */
- for_each_nb() {
+ for (i = 0; i < amd_nb_num(); i++) {
agp_bridge->gart_bus_addr =
- amd64_configure(hammers[gart_iterator],gatt_bus);
+ amd64_configure(node_to_amd_nb(i)->misc, gatt_bus);
}
+ amd_flush_garts();
return 0;
}
@@ -236,21 +197,27 @@ static int amd_8151_configure(void)
static void amd64_cleanup(void)
{
u32 tmp;
- int gart_iterator;
- for_each_nb() {
+ int i;
+
+ if (!amd_nb_has_feature(AMD_NB_GART))
+ return;
+
+ for (i = 0; i < amd_nb_num(); i++) {
+ struct pci_dev *dev = node_to_amd_nb(i)->misc;
/* disable gart translation */
- pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp);
- tmp &= ~AMD64_GARTEN;
- pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp);
+ pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp);
+ tmp &= ~GARTEN;
+ pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp);
}
}
-static struct agp_bridge_driver amd_8151_driver = {
+static const struct agp_bridge_driver amd_8151_driver = {
.owner = THIS_MODULE,
.aperture_sizes = amd_8151_sizes,
.size_type = U32_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = amd_8151_configure,
.fetch_size = amd64_fetch_size,
.cleanup = amd64_cleanup,
@@ -266,34 +233,17 @@ static struct agp_bridge_driver amd_8151_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
/* Some basic sanity checks for the aperture. */
-static int __devinit aperture_valid(u64 aper, u32 size)
+static int agp_aperture_valid(u64 aper, u32 size)
{
- u32 pfn, c;
- if (aper == 0) {
- printk(KERN_ERR PFX "No aperture\n");
- return 0;
- }
- if (size < 32*1024*1024) {
- printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20);
+ if (!aperture_valid(aper, size, 32*1024*1024))
return 0;
- }
- if (aper + size > 0xffffffff) {
- printk(KERN_ERR PFX "Aperture out of bounds\n");
- return 0;
- }
- pfn = aper >> PAGE_SHIFT;
- for (c = 0; c < size/PAGE_SIZE; c++) {
- if (!pfn_valid(pfn + c))
- break;
- if (!PageReserved(pfn_to_page(pfn + c))) {
- printk(KERN_ERR PFX "Aperture pointing to RAM\n");
- return 0;
- }
- }
/* Request the Aperture. This catches cases when someone else
already put a mapping in there - happens with some very broken BIOS
@@ -311,34 +261,32 @@ static int __devinit aperture_valid(u64 aper, u32 size)
/*
* W*s centric BIOS sometimes only set up the aperture in the AGP
* bridge, not the northbridge. On AMD64 this is handled early
- * in aperture.c, but when GART_IOMMU is not enabled or we run
+ * in aperture.c, but when IOMMU is not enabled or we run
* on a 32bit kernel this needs to be redone.
* Unfortunately it is impossible to fix the aperture here because it's too late
* to allocate that much memory. But at least error out cleanly instead of
* crashing.
*/
-static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
- u16 cap)
+static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap)
{
- u32 aper_low, aper_hi;
u64 aper, nb_aper;
int order = 0;
u32 nb_order, nb_base;
u16 apsize;
- pci_read_config_dword(nb, 0x90, &nb_order);
+ pci_read_config_dword(nb, AMD64_GARTAPERTURECTL, &nb_order);
nb_order = (nb_order >> 1) & 7;
- pci_read_config_dword(nb, 0x94, &nb_base);
+ pci_read_config_dword(nb, AMD64_GARTAPERTUREBASE, &nb_base);
nb_aper = nb_base << 25;
- if (aperture_valid(nb_aper, (32*1024*1024)<<nb_order)) {
- return 0;
- }
/* Northbridge seems to contain crap. Try the AGP bridge. */
pci_read_config_word(agp, cap+0x14, &apsize);
- if (apsize == 0xffff)
+ if (apsize == 0xffff) {
+ if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order))
+ return 0;
return -1;
+ }
apsize &= 0xfff;
/* Some BIOS use weird encodings not in the AGPv3 table. */
@@ -346,53 +294,65 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
apsize |= 0xf00;
order = 7 - hweight16(apsize);
- pci_read_config_dword(agp, 0x10, &aper_low);
- pci_read_config_dword(agp, 0x14, &aper_hi);
- aper = (aper_low & ~((1<<22)-1)) | ((u64)aper_hi << 32);
- printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order);
- if (order < 0 || !aperture_valid(aper, (32*1024*1024)<<order))
+ aper = pci_bus_address(agp, AGP_APERTURE_BAR);
+
+ /*
+ * On some sick chips APSIZE is 0. This means it wants 4G
+ * so let double check that order, and lets trust the AMD NB settings
+ */
+ if (order >=0 && aper + (32ULL<<(20 + order)) > 0x100000000ULL) {
+ dev_info(&agp->dev, "aperture size %u MB is not right, using settings from NB\n",
+ 32 << order);
+ order = nb_order;
+ }
+
+ if (nb_order >= order) {
+ if (agp_aperture_valid(nb_aper, (32*1024*1024)<<nb_order))
+ return 0;
+ }
+
+ dev_info(&agp->dev, "aperture from AGP @ %Lx size %u MB\n",
+ aper, 32 << order);
+ if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order))
return -1;
- pci_write_config_dword(nb, 0x90, order << 1);
- pci_write_config_dword(nb, 0x94, aper >> 25);
+ gart_set_size_and_enable(nb, order);
+ pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25);
return 0;
}
-static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
+static int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
{
- struct pci_dev *loop_dev = NULL;
- int i = 0;
-
- /* cache pci_devs of northbridges. */
- while ((loop_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
- != NULL) {
- if (i == MAX_HAMMER_GARTS) {
- printk(KERN_ERR PFX "Too many northbridges for AGP\n");
- return -1;
- }
- if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) {
- printk(KERN_ERR PFX "No usable aperture found.\n");
+ int i;
+
+ if (amd_cache_northbridges() < 0)
+ return -ENODEV;
+
+ if (!amd_nb_has_feature(AMD_NB_GART))
+ return -ENODEV;
+
+ i = 0;
+ for (i = 0; i < amd_nb_num(); i++) {
+ struct pci_dev *dev = node_to_amd_nb(i)->misc;
+ if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
+ dev_err(&dev->dev, "no usable aperture found\n");
#ifdef __x86_64__
/* should port this to i386 */
- printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n");
+ dev_err(&dev->dev, "consider rebooting with iommu=memaper=2 to get a good aperture\n");
#endif
return -1;
}
- hammers[i++] = loop_dev;
}
- nr_garts = i;
- return i == 0 ? -1 : 0;
+ return 0;
}
/* Handle AMD 8151 quirks */
-static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
+static void amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
{
char *revstring;
- u8 rev_id;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
- switch (rev_id) {
+ switch (pdev->revision) {
case 0x01: revstring="A0"; break;
case 0x02: revstring="A1"; break;
case 0x11: revstring="B0"; break;
@@ -402,14 +362,14 @@ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data
default: revstring="??"; break;
}
- printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring);
+ dev_info(&pdev->dev, "AMD 8151 AGP Bridge rev %s\n", revstring);
/*
* Work around errata.
* Chips before B2 stepping incorrectly reporting v3.5
*/
- if (rev_id < 0x13) {
- printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n");
+ if (pdev->revision < 0x13) {
+ dev_info(&pdev->dev, "correcting AGP revision (reports 3.5, is really 3.0)\n");
bridge->major_version = 3;
bridge->minor_version = 0;
}
@@ -426,17 +386,17 @@ static const struct aper_size_info_32 uli_sizes[7] =
{8, 2048, 1, 4},
{4, 1024, 0, 3}
};
-static int __devinit uli_agp_init(struct pci_dev *pdev)
+static int uli_agp_init(struct pci_dev *pdev)
{
u32 httfea,baseaddr,enuscr;
struct pci_dev *dev1;
- int i;
+ int i, ret;
unsigned size = amd64_fetch_size();
- printk(KERN_INFO "Setting up ULi AGP.\n");
- dev1 = pci_find_slot ((unsigned int)pdev->bus->number,PCI_DEVFN(0,0));
+
+ dev_info(&pdev->dev, "setting up ULi AGP\n");
+ dev1 = pci_get_slot (pdev->bus,PCI_DEVFN(0,0));
if (dev1 == NULL) {
- printk(KERN_INFO PFX "Detected a ULi chipset, "
- "but could not fine the secondary device.\n");
+ dev_info(&pdev->dev, "can't find ULi secondary device\n");
return -ENODEV;
}
@@ -445,16 +405,20 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
break;
if (i == ARRAY_SIZE(uli_sizes)) {
- printk(KERN_INFO PFX "No ULi size found for %d\n", size);
- return -ENODEV;
+ dev_info(&pdev->dev, "no ULi size found for %d\n", size);
+ ret = -ENODEV;
+ goto put;
}
/* shadow x86-64 registers into ULi registers */
- pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &httfea);
+ pci_read_config_dword (node_to_amd_nb(0)->misc, AMD64_GARTAPERTUREBASE,
+ &httfea);
/* if x86-64 aperture base is beyond 4G, exit here */
- if ((httfea & 0x7fff) >> (32 - 25))
- return -ENODEV;
+ if ((httfea & 0x7fff) >> (32 - 25)) {
+ ret = -ENODEV;
+ goto put;
+ }
httfea = (httfea& 0x7fff) << 25;
@@ -466,7 +430,10 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
enuscr= httfea+ (size * 1024 * 1024) - 1;
pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea);
pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr);
- return 0;
+ ret = 0;
+put:
+ pci_dev_put(dev1);
+ return ret;
}
@@ -481,20 +448,18 @@ static const struct aper_size_info_32 nforce3_sizes[5] =
/* Handle shadow device of the Nvidia NForce3 */
/* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */
-static int __devinit nforce3_agp_init(struct pci_dev *pdev)
+static int nforce3_agp_init(struct pci_dev *pdev)
{
u32 tmp, apbase, apbar, aplimit;
struct pci_dev *dev1;
- int i;
+ int i, ret;
unsigned size = amd64_fetch_size();
- printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n");
+ dev_info(&pdev->dev, "setting up Nforce3 AGP\n");
- dev1 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(11, 0));
+ dev1 = pci_get_slot(pdev->bus, PCI_DEVFN(11, 0));
if (dev1 == NULL) {
- printk(KERN_INFO PFX "agpgart: Detected an NVIDIA "
- "nForce3 chipset, but could not find "
- "the secondary device.\n");
+ dev_info(&pdev->dev, "can't find Nforce3 secondary device\n");
return -ENODEV;
}
@@ -503,8 +468,9 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
break;
if (i == ARRAY_SIZE(nforce3_sizes)) {
- printk(KERN_INFO PFX "No NForce3 size found for %d\n", size);
- return -ENODEV;
+ dev_info(&pdev->dev, "no NForce3 size found for %d\n", size);
+ ret = -ENODEV;
+ goto put;
}
pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp);
@@ -513,11 +479,15 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
/* shadow x86-64 registers into NVIDIA registers */
- pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase);
+ pci_read_config_dword (node_to_amd_nb(0)->misc, AMD64_GARTAPERTUREBASE,
+ &apbase);
/* if x86-64 aperture base is beyond 4G, exit here */
- if ( (apbase & 0x7fff) >> (32 - 25) )
- return -ENODEV;
+ if ( (apbase & 0x7fff) >> (32 - 25) ) {
+ dev_info(&pdev->dev, "aperture base > 4G\n");
+ ret = -ENODEV;
+ goto put;
+ }
apbase = (apbase & 0x7fff) << 25;
@@ -532,14 +502,23 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase);
pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit);
- return 0;
+ ret = 0;
+put:
+ pci_dev_put(dev1);
+
+ return ret;
}
-static int __devinit agp_amd64_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_amd64_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
u8 cap_ptr;
+ int err;
+
+ /* The Highlander principle */
+ if (agp_bridges_found)
+ return -ENODEV;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
@@ -555,7 +534,8 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
pdev->device == PCI_DEVICE_ID_AMD_8151_0) {
amd8151_init(pdev, bridge);
} else {
- printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn);
+ dev_info(&pdev->dev, "AGP bridge [%04x/%04x]\n",
+ pdev->vendor, pdev->device);
}
bridge->driver = &amd_8151_driver;
@@ -587,17 +567,24 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev,
}
pci_set_drvdata(pdev, bridge);
- return agp_add_bridge(bridge);
+ err = agp_add_bridge(bridge);
+ if (err < 0)
+ return err;
+
+ agp_bridges_found++;
+ return 0;
}
-static void __devexit agp_amd64_remove(struct pci_dev *pdev)
+static void agp_amd64_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- release_mem_region(virt_to_gart(bridge->gatt_table_real),
+ release_mem_region(virt_to_phys(bridge->gatt_table_real),
amd64_aperture_sizes[bridge->aperture_size_idx].size);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
+
+ agp_bridges_found--;
}
#ifdef CONFIG_PM
@@ -615,6 +602,9 @@ static int agp_amd64_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
+ if (pdev->vendor == PCI_VENDOR_ID_NVIDIA)
+ nforce3_agp_init(pdev);
+
return amd_8151_configure();
}
@@ -665,6 +655,15 @@ static struct pci_device_id agp_amd64_pci_table[] = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
+ /* VIA K8M890 / K8N890 */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_VT3336,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
/* VIA K8T890 */
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
@@ -723,7 +722,7 @@ static struct pci_device_id agp_amd64_pci_table[] = {
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_AL,
- .device = 0x1689,
+ .device = 0x1695,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
@@ -733,6 +732,11 @@ static struct pci_device_id agp_amd64_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table);
+static const struct pci_device_id agp_amd64_pci_promisc_table[] = {
+ { PCI_DEVICE_CLASS(0, 0) },
+ { }
+};
+
static struct pci_driver agp_amd64_pci_driver = {
.name = "agpgart-amd64",
.id_table = agp_amd64_pci_table,
@@ -749,15 +753,15 @@ static struct pci_driver agp_amd64_pci_driver = {
int __init agp_amd64_init(void)
{
int err = 0;
- static struct pci_device_id amd64nb[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
- { },
- };
if (agp_off)
return -EINVAL;
- if (pci_register_driver(&agp_amd64_pci_driver) > 0) {
- struct pci_dev *dev;
+
+ err = pci_register_driver(&agp_amd64_pci_driver);
+ if (err < 0)
+ return err;
+
+ if (agp_bridges_found == 0) {
if (!agp_try_unsupported && !agp_try_unsupported_boot) {
printk(KERN_INFO PFX "No supported AGP bridge found.\n");
#ifdef MODULE
@@ -765,43 +769,50 @@ int __init agp_amd64_init(void)
#else
printk(KERN_INFO PFX "You can boot with agp=try_unsupported\n");
#endif
+ pci_unregister_driver(&agp_amd64_pci_driver);
return -ENODEV;
}
/* First check that we have at least one AMD64 NB */
- if (!pci_dev_present(amd64nb))
+ if (!pci_dev_present(amd_nb_misc_ids)) {
+ pci_unregister_driver(&agp_amd64_pci_driver);
return -ENODEV;
+ }
/* Look for any AGP bridge */
- dev = NULL;
- err = -ENODEV;
- for_each_pci_dev(dev) {
- if (!pci_find_capability(dev, PCI_CAP_ID_AGP))
- continue;
- /* Only one bridge supported right now */
- if (agp_amd64_probe(dev, NULL) == 0) {
- err = 0;
- break;
- }
+ agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table;
+ err = driver_attach(&agp_amd64_pci_driver.driver);
+ if (err == 0 && agp_bridges_found == 0) {
+ pci_unregister_driver(&agp_amd64_pci_driver);
+ err = -ENODEV;
}
}
return err;
}
+static int __init agp_amd64_mod_init(void)
+{
+#ifndef MODULE
+ if (gart_iommu_aperture)
+ return agp_bridges_found ? 0 : -ENODEV;
+#endif
+ return agp_amd64_init();
+}
+
static void __exit agp_amd64_cleanup(void)
{
+#ifndef MODULE
+ if (gart_iommu_aperture)
+ return;
+#endif
if (aperture_resource)
release_resource(aperture_resource);
pci_unregister_driver(&agp_amd64_pci_driver);
}
-/* On AMD64 the PCI driver needs to initialize this driver early
- for the IOMMU, so it has to be called via a backdoor. */
-#ifndef CONFIG_GART_IOMMU
-module_init(agp_amd64_init);
+module_init(agp_amd64_mod_init);
module_exit(agp_amd64_cleanup);
-#endif
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>, Andi Kleen");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>, Andi Kleen");
module_param(agp_try_unsupported, bool, 0);
MODULE_LICENSE("GPL");
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 5b74c36c116..18a7a6baa30 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -12,7 +12,7 @@
#include <asm/agp.h>
#include "agp.h"
-#define ATI_GART_MMBASE_ADDR 0x14
+#define ATI_GART_MMBASE_BAR 1
#define ATI_RS100_APSIZE 0xac
#define ATI_RS100_IG_AGPMODE 0xb0
#define ATI_RS300_APSIZE 0xf8
@@ -24,7 +24,7 @@
#define ATI_GART_CACHE_ENTRY_CNTRL 0x10
-static struct aper_size_info_lvl2 ati_generic_sizes[7] =
+static const struct aper_size_info_lvl2 ati_generic_sizes[7] =
{
{2048, 524288, 0x0000000c},
{1024, 262144, 0x0000000a},
@@ -41,19 +41,18 @@ static struct gatt_mask ati_generic_masks[] =
};
-
-typedef struct _ati_page_map {
+struct ati_page_map {
unsigned long *real;
unsigned long __iomem *remapped;
-} ati_page_map;
+};
static struct _ati_generic_private {
volatile u8 __iomem *registers;
- ati_page_map **gatt_pages;
+ struct ati_page_map **gatt_pages;
int num_tables;
} ati_generic_private;
-static int ati_create_page_map(ati_page_map *page_map)
+static int ati_create_page_map(struct ati_page_map *page_map)
{
int i, err = 0;
@@ -61,20 +60,11 @@ static int ati_create_page_map(ati_page_map *page_map)
if (page_map->real == NULL)
return -ENOMEM;
- SetPageReserved(virt_to_page(page_map->real));
+ set_memory_uc((unsigned long)page_map->real, 1);
err = map_page_into_agp(virt_to_page(page_map->real));
- page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
- PAGE_SIZE);
- if (page_map->remapped == NULL || err) {
- ClearPageReserved(virt_to_page(page_map->real));
- free_page((unsigned long) page_map->real);
- page_map->real = NULL;
- return -ENOMEM;
- }
- /*CACHE_FLUSH();*/
- global_cache_flush();
+ page_map->remapped = page_map->real;
- for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
+ for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
writel(agp_bridge->scratch_page, page_map->remapped+i);
readl(page_map->remapped+i); /* PCI Posting. */
}
@@ -83,11 +73,10 @@ static int ati_create_page_map(ati_page_map *page_map)
}
-static void ati_free_page_map(ati_page_map *page_map)
+static void ati_free_page_map(struct ati_page_map *page_map)
{
unmap_page_from_agp(virt_to_page(page_map->real));
- iounmap(page_map->remapped);
- ClearPageReserved(virt_to_page(page_map->real));
+ set_memory_wb((unsigned long)page_map->real, 1);
free_page((unsigned long) page_map->real);
}
@@ -95,11 +84,11 @@ static void ati_free_page_map(ati_page_map *page_map)
static void ati_free_gatt_pages(void)
{
int i;
- ati_page_map **tables;
- ati_page_map *entry;
+ struct ati_page_map **tables;
+ struct ati_page_map *entry;
tables = ati_generic_private.gatt_pages;
- for(i = 0; i < ati_generic_private.num_tables; i++) {
+ for (i = 0; i < ati_generic_private.num_tables; i++) {
entry = tables[i];
if (entry != NULL) {
if (entry->real != NULL)
@@ -113,35 +102,31 @@ static void ati_free_gatt_pages(void)
static int ati_create_gatt_pages(int nr_tables)
{
- ati_page_map **tables;
- ati_page_map *entry;
+ struct ati_page_map **tables;
+ struct ati_page_map *entry;
int retval = 0;
int i;
- tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL);
+ tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
for (i = 0; i < nr_tables; i++) {
- entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL);
+ entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL);
+ tables[i] = entry;
if (entry == NULL) {
- while (i>0) {
- kfree (tables[i-1]);
- i--;
- }
- kfree (tables);
- tables = NULL;
retval = -ENOMEM;
break;
}
- tables[i] = entry;
retval = ati_create_page_map(entry);
- if (retval != 0) break;
+ if (retval != 0)
+ break;
}
- ati_generic_private.num_tables = nr_tables;
+ ati_generic_private.num_tables = i;
ati_generic_private.gatt_pages = tables;
- if (retval != 0) ati_free_gatt_pages();
+ if (retval != 0)
+ ati_free_gatt_pages();
return retval;
}
@@ -211,30 +196,33 @@ static void ati_cleanup(void)
static int ati_configure(void)
{
+ phys_addr_t reg;
u32 temp;
/* Get the memory mapped registers */
- pci_read_config_dword(agp_bridge->dev, ATI_GART_MMBASE_ADDR, &temp);
- temp = (temp & 0xfffff000);
- ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
+ reg = pci_resource_start(agp_bridge->dev, ATI_GART_MMBASE_BAR);
+ ati_generic_private.registers = (volatile u8 __iomem *) ioremap(reg, 4096);
+
+ if (!ati_generic_private.registers)
+ return -ENOMEM;
if (is_r200())
- pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
+ pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
else
pci_write_config_dword(agp_bridge->dev, ATI_RS300_IG_AGPMODE, 0x20000);
- /* address to map too */
- /*
- pci_read_config_dword(agp_bridge.dev, AGP_APBASE, &temp);
- agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ /* address to map to */
+ /*
+ agp_bridge.gart_bus_addr = pci_bus_address(agp_bridge.dev,
+ AGP_APERTURE_BAR);
printk(KERN_INFO PFX "IGP320 gart_bus_addr: %x\n", agp_bridge.gart_bus_addr);
- */
+ */
writel(0x60000, ati_generic_private.registers+ATI_GART_FEATURE_ID);
readl(ati_generic_private.registers+ATI_GART_FEATURE_ID); /* PCI Posting.*/
/* SIGNALED_SYSTEM_ERROR @ NB_STATUS */
- pci_read_config_dword(agp_bridge->dev, 4, &temp);
- pci_write_config_dword(agp_bridge->dev, 4, temp | (1<<14));
+ pci_read_config_dword(agp_bridge->dev, PCI_COMMAND, &temp);
+ pci_write_config_dword(agp_bridge->dev, PCI_COMMAND, temp | (1<<14));
/* Write out the address of the gatt table */
writel(agp_bridge->gatt_bus_addr, ati_generic_private.registers+ATI_GART_BASE);
@@ -245,23 +233,25 @@ static int ati_configure(void)
#ifdef CONFIG_PM
-static int agp_ati_resume(struct pci_dev *dev)
+static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
{
- pci_restore_state(dev);
+ pci_save_state(dev);
+ pci_set_power_state(dev, PCI_D3hot);
- return ati_configure();
+ return 0;
}
-static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
+static int agp_ati_resume(struct pci_dev *dev)
{
- pci_save_state(dev);
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
- return 0;
+ return ati_configure();
}
#endif
/*
- *Since we don't need contigious memory we just try
+ *Since we don't need contiguous memory we just try
* to get the gatt table once
*/
@@ -279,12 +269,17 @@ static int ati_insert_memory(struct agp_memory * mem,
int i, j, num_entries;
unsigned long __iomem *cur_gatt;
unsigned long addr;
+ int mask_type;
num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
- if (type != 0 || mem->type != 0)
+ mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+ if (mask_type != 0 || type != mem->type)
return -EINVAL;
+ if (mem->page_count == 0)
+ return 0;
+
if ((pg_start + mem->page_count) > num_entries)
return -EINVAL;
@@ -297,19 +292,21 @@ static int ati_insert_memory(struct agp_memory * mem,
j++;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
/*CACHE_FLUSH(); */
global_cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
- writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
- readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ page_to_phys(mem->pages[i]),
+ mem->type),
+ cur_gatt+GET_GATT_OFF(addr));
}
+ readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -320,17 +317,22 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
int i;
unsigned long __iomem *cur_gatt;
unsigned long addr;
+ int mask_type;
- if (type != 0 || mem->type != 0) {
+ mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+ if (mask_type != 0 || type != mem->type)
return -EINVAL;
- }
+
+ if (mem->page_count == 0)
+ return 0;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
- readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
}
+ readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -338,7 +340,8 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
static int ati_create_gatt_table(struct agp_bridge_data *bridge)
{
struct aper_size_info_lvl2 *value;
- ati_page_map page_dir;
+ struct ati_page_map page_dir;
+ unsigned long __iomem *cur_gatt;
unsigned long addr;
int retval;
u32 temp;
@@ -358,7 +361,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
/* Write out the size register */
current_size = A_SIZE_LVL2(agp_bridge->current_size);
@@ -382,23 +385,28 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
* This is a bus address even on the alpha, b/c its
* used to program the agp master not the cpu
*/
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
agp_bridge->gart_bus_addr = addr;
/* Calculate the agp offset */
- for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
+ for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
+ writel(virt_to_phys(ati_generic_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
+ for (i = 0; i < value->num_entries; i++) {
+ addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
+ cur_gatt = GET_GATT(addr);
+ writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
+ }
+
return 0;
}
static int ati_free_gatt_table(struct agp_bridge_data *bridge)
{
- ati_page_map page_dir;
+ struct ati_page_map page_dir;
page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
@@ -408,11 +416,12 @@ static int ati_free_gatt_table(struct agp_bridge_data *bridge)
return 0;
}
-static struct agp_bridge_driver ati_generic_bridge = {
+static const struct agp_bridge_driver ati_generic_bridge = {
.owner = THIS_MODULE,
.aperture_sizes = ati_generic_sizes,
.size_type = LVL2_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = ati_configure,
.fetch_size = ati_fetch_size,
.cleanup = ati_cleanup,
@@ -428,11 +437,14 @@ static struct agp_bridge_driver ati_generic_bridge = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
+static struct agp_device_ids ati_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_ATI_RS100,
@@ -466,11 +478,18 @@ static struct agp_device_ids ati_agp_device_ids[] __devinitdata =
.device_id = PCI_DEVICE_ID_ATI_RS300_200,
.chipset_name = "IGP9100/M",
},
+ {
+ .device_id = PCI_DEVICE_ID_ATI_RS350_133,
+ .chipset_name = "IGP9000/M",
+ },
+ {
+ .device_id = PCI_DEVICE_ID_ATI_RS350_200,
+ .chipset_name = "IGP9100/M",
+ },
{ }, /* dummy final entry, always present */
};
-static int __devinit agp_ati_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_ati_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct agp_device_ids *devs = ati_agp_device_ids;
struct agp_bridge_data *bridge;
@@ -487,8 +506,8 @@ static int __devinit agp_ati_probe(struct pci_dev *pdev,
goto found;
}
- printk(KERN_ERR PFX
- "Unsupported Ati chipset (device id: %04x)\n", pdev->device);
+ dev_err(&pdev->dev, "unsupported Ati chipset [%04x/%04x])\n",
+ pdev->vendor, pdev->device);
return -ENODEV;
found:
@@ -498,12 +517,10 @@ found:
bridge->dev = pdev;
bridge->capndx = cap_ptr;
-
- bridge->driver = &ati_generic_bridge;
+ bridge->driver = &ati_generic_bridge;
- printk(KERN_INFO PFX "Detected Ati %s chipset\n",
- devs[j].chipset_name);
+ dev_info(&pdev->dev, "Ati %s chipset\n", devs[j].chipset_name);
/* Fill in the mode register */
pci_read_config_dword(pdev,
@@ -514,7 +531,7 @@ found:
return agp_add_bridge(bridge);
}
-static void __devexit agp_ati_remove(struct pci_dev *pdev)
+static void agp_ati_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -542,8 +559,8 @@ static struct pci_driver agp_ati_pci_driver = {
.probe = agp_ati_probe,
.remove = agp_ati_remove,
#ifdef CONFIG_PM
- .resume = agp_ati_resume,
.suspend = agp_ati_suspend,
+ .resume = agp_ati_resume,
#endif
};
@@ -562,6 +579,6 @@ static void __exit agp_ati_cleanup(void)
module_init(agp_ati_init);
module_exit(agp_ati_cleanup);
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 80ee17a8fc2..317c28ce832 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/miscdevice.h>
#include <linux/pm.h>
@@ -43,8 +44,8 @@
* fix some real stupidity. It's only by chance we can bump
* past 0.99 at all due to some boolean logic error. */
#define AGPGART_VERSION_MAJOR 0
-#define AGPGART_VERSION_MINOR 101
-static struct agp_version agp_current_version =
+#define AGPGART_VERSION_MINOR 103
+static const struct agp_version agp_current_version =
{
.major = AGPGART_VERSION_MAJOR,
.minor = AGPGART_VERSION_MINOR,
@@ -114,9 +115,9 @@ static int agp_find_max(void)
long memory, index, result;
#if PAGE_SHIFT < 20
- memory = num_physpages >> (20 - PAGE_SHIFT);
+ memory = totalram_pages >> (20 - PAGE_SHIFT);
#else
- memory = num_physpages << (PAGE_SHIFT - 20);
+ memory = totalram_pages << (PAGE_SHIFT - 20);
#endif
index = 1;
@@ -141,57 +142,62 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
bridge->version = &agp_current_version;
if (bridge->driver->needs_scratch_page) {
- void *addr = bridge->driver->agp_alloc_page(bridge);
+ struct page *page = bridge->driver->agp_alloc_page(bridge);
- if (!addr) {
- printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
+ if (!page) {
+ dev_err(&bridge->dev->dev,
+ "can't get memory for scratch page\n");
return -ENOMEM;
}
- flush_agp_mappings();
- bridge->scratch_page_real = virt_to_gart(addr);
- bridge->scratch_page =
- bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
+ bridge->scratch_page_page = page;
+ bridge->scratch_page_dma = page_to_phys(page);
+
+ bridge->scratch_page = bridge->driver->mask_memory(bridge,
+ bridge->scratch_page_dma, 0);
}
size_value = bridge->driver->fetch_size();
if (size_value == 0) {
- printk(KERN_ERR PFX "unable to determine aperture size.\n");
+ dev_err(&bridge->dev->dev, "can't determine aperture size\n");
rc = -EINVAL;
goto err_out;
}
if (bridge->driver->create_gatt_table(bridge)) {
- printk(KERN_ERR PFX
- "unable to get memory for graphics translation table.\n");
+ dev_err(&bridge->dev->dev,
+ "can't get memory for graphics translation table\n");
rc = -ENOMEM;
goto err_out;
}
got_gatt = 1;
- bridge->key_list = vmalloc(PAGE_SIZE * 4);
+ bridge->key_list = vzalloc(PAGE_SIZE * 4);
if (bridge->key_list == NULL) {
- printk(KERN_ERR PFX "error allocating memory for key lists.\n");
+ dev_err(&bridge->dev->dev,
+ "can't allocate memory for key lists\n");
rc = -ENOMEM;
goto err_out;
}
got_keylist = 1;
/* FIXME vmalloc'd memory not guaranteed contiguous */
- memset(bridge->key_list, 0, PAGE_SIZE * 4);
if (bridge->driver->configure()) {
- printk(KERN_ERR PFX "error configuring host chipset.\n");
+ dev_err(&bridge->dev->dev, "error configuring host chipset\n");
rc = -EINVAL;
goto err_out;
}
+ INIT_LIST_HEAD(&bridge->mapped_list);
+ spin_lock_init(&bridge->mapped_lock);
return 0;
err_out:
if (bridge->driver->needs_scratch_page) {
- bridge->driver->agp_destroy_page(
- gart_to_virt(bridge->scratch_page_real));
- flush_agp_mappings();
+ struct page *page = bridge->scratch_page_page;
+
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
}
if (got_gatt)
bridge->driver->free_gatt_table(bridge);
@@ -215,9 +221,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page) {
- bridge->driver->agp_destroy_page(
- gart_to_virt(bridge->scratch_page_real));
- flush_agp_mappings();
+ struct page *page = bridge->scratch_page_page;
+
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
}
}
@@ -228,7 +235,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
struct agp_bridge_data *agp_alloc_bridge(void)
{
struct agp_bridge_data *bridge;
-
+
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
if (!bridge)
return NULL;
@@ -258,35 +265,41 @@ int agp_add_bridge(struct agp_bridge_data *bridge)
{
int error;
- if (agp_off)
- return -ENODEV;
+ if (agp_off) {
+ error = -ENODEV;
+ goto err_put_bridge;
+ }
if (!bridge->dev) {
printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n");
- return -EINVAL;
+ error = -EINVAL;
+ goto err_put_bridge;
}
/* Grab reference on the chipset driver. */
if (!try_module_get(bridge->driver->owner)) {
- printk (KERN_INFO PFX "Couldn't lock chipset driver.\n");
- return -EINVAL;
+ dev_info(&bridge->dev->dev, "can't lock chipset driver\n");
+ error = -EINVAL;
+ goto err_put_bridge;
}
error = agp_backend_initialize(bridge);
if (error) {
- printk (KERN_INFO PFX "agp_backend_initialize() failed.\n");
+ dev_info(&bridge->dev->dev,
+ "agp_backend_initialize() failed\n");
goto err_out;
}
if (list_empty(&agp_bridges)) {
error = agp_frontend_initialize();
if (error) {
- printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n");
+ dev_info(&bridge->dev->dev,
+ "agp_frontend_initialize() failed\n");
goto frontend_err;
}
- printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
- bridge->driver->fetch_size(), bridge->gart_bus_addr);
+ dev_info(&bridge->dev->dev, "AGP aperture is %dM @ 0x%lx\n",
+ bridge->driver->fetch_size(), bridge->gart_bus_addr);
}
@@ -297,6 +310,7 @@ frontend_err:
agp_backend_cleanup(bridge);
err_out:
module_put(bridge->driver->owner);
+err_put_bridge:
agp_put_bridge(bridge);
return error;
}
@@ -321,7 +335,7 @@ EXPORT_SYMBOL(agp_try_unsupported_boot);
static int __init agp_init(void)
{
if (!agp_off)
- printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
+ printk(KERN_INFO "Linux agpgart interface v%d.%d\n",
AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
return 0;
}
@@ -342,7 +356,7 @@ static __init int agp_setup(char *s)
__setup("agp=", agp_setup);
#endif
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_DESCRIPTION("AGP GART driver");
MODULE_LICENSE("GPL and additional rights");
MODULE_ALIAS_MISCDEV(AGPGART_MINOR);
diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c
new file mode 100644
index 00000000000..a48e05b3159
--- /dev/null
+++ b/drivers/char/agp/compat_ioctl.c
@@ -0,0 +1,287 @@
+/*
+ * AGPGART driver frontend compatibility ioctls
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ * Copyright (C) 2002-2003 Dave Jones
+ * Copyright (C) 1999 Jeff Hartmann
+ * Copyright (C) 1999 Precision Insight, Inc.
+ * Copyright (C) 1999 Xi Graphics, Inc.
+ *
+ * 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 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
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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 <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/agpgart.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include "agp.h"
+#include "compat_ioctl.h"
+
+static int compat_agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
+{
+ struct agp_info32 userinfo;
+ struct agp_kern_info kerninfo;
+
+ agp_copy_info(agp_bridge, &kerninfo);
+
+ userinfo.version.major = kerninfo.version.major;
+ userinfo.version.minor = kerninfo.version.minor;
+ userinfo.bridge_id = kerninfo.device->vendor |
+ (kerninfo.device->device << 16);
+ userinfo.agp_mode = kerninfo.mode;
+ userinfo.aper_base = (compat_long_t)kerninfo.aper_base;
+ userinfo.aper_size = kerninfo.aper_size;
+ userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory;
+ userinfo.pg_used = kerninfo.current_memory;
+
+ if (copy_to_user(arg, &userinfo, sizeof(userinfo)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
+{
+ struct agp_region32 ureserve;
+ struct agp_region kreserve;
+ struct agp_client *client;
+ struct agp_file_private *client_priv;
+
+ DBG("");
+ if (copy_from_user(&ureserve, arg, sizeof(ureserve)))
+ return -EFAULT;
+
+ if ((unsigned) ureserve.seg_count >= ~0U/sizeof(struct agp_segment32))
+ return -EFAULT;
+
+ kreserve.pid = ureserve.pid;
+ kreserve.seg_count = ureserve.seg_count;
+
+ client = agp_find_client_by_pid(kreserve.pid);
+
+ if (kreserve.seg_count == 0) {
+ /* remove a client */
+ client_priv = agp_find_private(kreserve.pid);
+
+ if (client_priv != NULL) {
+ set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+ set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
+ }
+ if (client == NULL) {
+ /* client is already removed */
+ return 0;
+ }
+ return agp_remove_client(kreserve.pid);
+ } else {
+ struct agp_segment32 *usegment;
+ struct agp_segment *ksegment;
+ int seg;
+
+ if (ureserve.seg_count >= 16384)
+ return -EINVAL;
+
+ usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL);
+ if (!usegment)
+ return -ENOMEM;
+
+ ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL);
+ if (!ksegment) {
+ kfree(usegment);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(usegment, (void __user *) ureserve.seg_list,
+ sizeof(*usegment) * ureserve.seg_count)) {
+ kfree(usegment);
+ kfree(ksegment);
+ return -EFAULT;
+ }
+
+ for (seg = 0; seg < ureserve.seg_count; seg++) {
+ ksegment[seg].pg_start = usegment[seg].pg_start;
+ ksegment[seg].pg_count = usegment[seg].pg_count;
+ ksegment[seg].prot = usegment[seg].prot;
+ }
+
+ kfree(usegment);
+ kreserve.seg_list = ksegment;
+
+ if (client == NULL) {
+ /* Create the client and add the segment */
+ client = agp_create_client(kreserve.pid);
+
+ if (client == NULL) {
+ kfree(ksegment);
+ return -ENOMEM;
+ }
+ client_priv = agp_find_private(kreserve.pid);
+
+ if (client_priv != NULL) {
+ set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags);
+ set_bit(AGP_FF_IS_VALID, &client_priv->access_flags);
+ }
+ }
+ return agp_create_segment(client, &kreserve);
+ }
+ /* Will never really happen */
+ return -EINVAL;
+}
+
+static int compat_agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
+{
+ struct agp_memory *memory;
+ struct agp_allocate32 alloc;
+
+ DBG("");
+ if (copy_from_user(&alloc, arg, sizeof(alloc)))
+ return -EFAULT;
+
+ memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
+
+ if (memory == NULL)
+ return -ENOMEM;
+
+ alloc.key = memory->key;
+ alloc.physical = memory->physical;
+
+ if (copy_to_user(arg, &alloc, sizeof(alloc))) {
+ agp_free_memory_wrap(memory);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int compat_agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg)
+{
+ struct agp_bind32 bind_info;
+ struct agp_memory *memory;
+
+ DBG("");
+ if (copy_from_user(&bind_info, arg, sizeof(bind_info)))
+ return -EFAULT;
+
+ memory = agp_find_mem_by_key(bind_info.key);
+
+ if (memory == NULL)
+ return -EINVAL;
+
+ return agp_bind_memory(memory, bind_info.pg_start);
+}
+
+static int compat_agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
+{
+ struct agp_memory *memory;
+ struct agp_unbind32 unbind;
+
+ DBG("");
+ if (copy_from_user(&unbind, arg, sizeof(unbind)))
+ return -EFAULT;
+
+ memory = agp_find_mem_by_key(unbind.key);
+
+ if (memory == NULL)
+ return -EINVAL;
+
+ return agp_unbind_memory(memory);
+}
+
+long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct agp_file_private *curr_priv = file->private_data;
+ int ret_val = -ENOTTY;
+
+ mutex_lock(&(agp_fe.agp_mutex));
+
+ if ((agp_fe.current_controller == NULL) &&
+ (cmd != AGPIOC_ACQUIRE32)) {
+ ret_val = -EINVAL;
+ goto ioctl_out;
+ }
+ if ((agp_fe.backend_acquired != true) &&
+ (cmd != AGPIOC_ACQUIRE32)) {
+ ret_val = -EBUSY;
+ goto ioctl_out;
+ }
+ if (cmd != AGPIOC_ACQUIRE32) {
+ if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
+ ret_val = -EPERM;
+ goto ioctl_out;
+ }
+ /* Use the original pid of the controller,
+ * in case it's threaded */
+
+ if (agp_fe.current_controller->pid != curr_priv->my_pid) {
+ ret_val = -EBUSY;
+ goto ioctl_out;
+ }
+ }
+
+ switch (cmd) {
+ case AGPIOC_INFO32:
+ ret_val = compat_agpioc_info_wrap(curr_priv, (void __user *) arg);
+ break;
+
+ case AGPIOC_ACQUIRE32:
+ ret_val = agpioc_acquire_wrap(curr_priv);
+ break;
+
+ case AGPIOC_RELEASE32:
+ ret_val = agpioc_release_wrap(curr_priv);
+ break;
+
+ case AGPIOC_SETUP32:
+ ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
+ break;
+
+ case AGPIOC_RESERVE32:
+ ret_val = compat_agpioc_reserve_wrap(curr_priv, (void __user *) arg);
+ break;
+
+ case AGPIOC_PROTECT32:
+ ret_val = agpioc_protect_wrap(curr_priv);
+ break;
+
+ case AGPIOC_ALLOCATE32:
+ ret_val = compat_agpioc_allocate_wrap(curr_priv, (void __user *) arg);
+ break;
+
+ case AGPIOC_DEALLOCATE32:
+ ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
+ break;
+
+ case AGPIOC_BIND32:
+ ret_val = compat_agpioc_bind_wrap(curr_priv, (void __user *) arg);
+ break;
+
+ case AGPIOC_UNBIND32:
+ ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg);
+ break;
+
+ case AGPIOC_CHIPSET_FLUSH32:
+ break;
+ }
+
+ioctl_out:
+ DBG("ioctl returns %d\n", ret_val);
+ mutex_unlock(&(agp_fe.agp_mutex));
+ return ret_val;
+}
+
diff --git a/drivers/char/agp/compat_ioctl.h b/drivers/char/agp/compat_ioctl.h
new file mode 100644
index 00000000000..f30e0fd9796
--- /dev/null
+++ b/drivers/char/agp/compat_ioctl.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 1999 Jeff Hartmann
+ * Copyright (C) 1999 Precision Insight, Inc.
+ * Copyright (C) 1999 Xi Graphics, Inc.
+ *
+ * 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 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
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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.
+ *
+ */
+
+#ifndef _AGP_COMPAT_IOCTL_H
+#define _AGP_COMPAT_IOCTL_H
+
+#include <linux/compat.h>
+#include <linux/agpgart.h>
+
+#define AGPIOC_INFO32 _IOR (AGPIOC_BASE, 0, compat_uptr_t)
+#define AGPIOC_ACQUIRE32 _IO (AGPIOC_BASE, 1)
+#define AGPIOC_RELEASE32 _IO (AGPIOC_BASE, 2)
+#define AGPIOC_SETUP32 _IOW (AGPIOC_BASE, 3, compat_uptr_t)
+#define AGPIOC_RESERVE32 _IOW (AGPIOC_BASE, 4, compat_uptr_t)
+#define AGPIOC_PROTECT32 _IOW (AGPIOC_BASE, 5, compat_uptr_t)
+#define AGPIOC_ALLOCATE32 _IOWR(AGPIOC_BASE, 6, compat_uptr_t)
+#define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t)
+#define AGPIOC_BIND32 _IOW (AGPIOC_BASE, 8, compat_uptr_t)
+#define AGPIOC_UNBIND32 _IOW (AGPIOC_BASE, 9, compat_uptr_t)
+#define AGPIOC_CHIPSET_FLUSH32 _IO (AGPIOC_BASE, 10)
+
+struct agp_info32 {
+ struct agp_version version; /* version of the driver */
+ u32 bridge_id; /* bridge vendor/device */
+ u32 agp_mode; /* mode info of bridge */
+ compat_long_t aper_base; /* base of aperture */
+ compat_size_t aper_size; /* size of aperture */
+ compat_size_t pg_total; /* max pages (swap + system) */
+ compat_size_t pg_system; /* max pages (system) */
+ compat_size_t pg_used; /* current pages used */
+};
+
+/*
+ * The "prot" down below needs still a "sleep" flag somehow ...
+ */
+struct agp_segment32 {
+ compat_off_t pg_start; /* starting page to populate */
+ compat_size_t pg_count; /* number of pages */
+ compat_int_t prot; /* prot flags for mmap */
+};
+
+struct agp_region32 {
+ compat_pid_t pid; /* pid of process */
+ compat_size_t seg_count; /* number of segments */
+ struct agp_segment32 *seg_list;
+};
+
+struct agp_allocate32 {
+ compat_int_t key; /* tag of allocation */
+ compat_size_t pg_count; /* number of pages */
+ u32 type; /* 0 == normal, other devspec */
+ u32 physical; /* device specific (some devices
+ * need a phys address of the
+ * actual page behind the gatt
+ * table) */
+};
+
+struct agp_bind32 {
+ compat_int_t key; /* tag of allocation */
+ compat_off_t pg_start; /* starting page to populate */
+};
+
+struct agp_unbind32 {
+ compat_int_t key; /* tag of allocation */
+ u32 priority; /* priority for paging out */
+};
+
+extern struct agp_front_data agp_fe;
+
+int agpioc_acquire_wrap(struct agp_file_private *priv);
+int agpioc_release_wrap(struct agp_file_private *priv);
+int agpioc_protect_wrap(struct agp_file_private *priv);
+int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg);
+int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg);
+struct agp_file_private *agp_find_private(pid_t pid);
+struct agp_client *agp_create_client(pid_t id);
+int agp_remove_client(pid_t id);
+int agp_create_segment(struct agp_client *client, struct agp_region *region);
+void agp_free_memory_wrap(struct agp_memory *memory);
+struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type);
+struct agp_memory *agp_find_mem_by_key(int key);
+struct agp_client *agp_find_client_by_pid(pid_t id);
+
+#endif /* _AGP_COMPAT_H */
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index e7aea77a60f..533cb6d229b 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -1,6 +1,6 @@
/*
* Transmeta's Efficeon AGPGART driver.
- *
+ *
* Based upon a diff by Linus around November '02.
*
* Ported to the 2.6 kernel by Carlos Puchol <cpglinux@puchol.com>
@@ -9,7 +9,7 @@
/*
* NOTE-cpg-040217:
- *
+ *
* - when compiled as a module, after loading the module,
* it will refuse to unload, indicating it is in use,
* when it is not.
@@ -28,6 +28,7 @@
#include <linux/page-flags.h>
#include <linux/mm.h>
#include "agp.h"
+#include "intel-agp.h"
/*
* The real differences to the generic AGP code is
@@ -45,7 +46,7 @@
* 8: Present
* 7:6: reserved, write as zero
* 5:0: GATT directory index: which 1st-level entry
- *
+ *
* The Efficeon AGP spec requires pages to be WB-cacheable
* but to be explicitly CLFLUSH'd after any changes.
*/
@@ -59,12 +60,19 @@ static struct _efficeon_private {
unsigned long l1_table[EFFICEON_L1_SIZE];
} efficeon_private;
-static struct gatt_mask efficeon_generic_masks[] =
+static const struct gatt_mask efficeon_generic_masks[] =
{
{.mask = 0x00000001, .type = 0}
};
-static struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
+/* This function does the same thing as mask_memory() for this chipset... */
+static inline unsigned long efficeon_mask_memory(struct page *page)
+{
+ unsigned long addr = page_to_phys(page);
+ return addr | 0x00000001;
+}
+
+static const struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
{
{256, 65536, 0},
{128, 32768, 32},
@@ -120,12 +128,11 @@ static void efficeon_cleanup(void)
static int efficeon_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_lvl2 *current_size;
printk(KERN_DEBUG PFX "efficeon_configure()\n");
-
+
current_size = A_SIZE_LVL2(agp_bridge->current_size);
/* aperture size */
@@ -133,8 +140,8 @@ static int efficeon_configure(void)
current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* agpctrl */
pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
@@ -171,7 +178,7 @@ static int efficeon_free_gatt_table(struct agp_bridge_data *bridge)
/*
- * Since we don't need contigious memory we just try
+ * Since we don't need contiguous memory we just try
* to get the gatt table once
*/
@@ -190,7 +197,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
const int present = EFFICEON_PRESENT;
const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
int num_entries, l1_pages;
-
+
num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries);
@@ -215,11 +222,11 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
SetPageReserved(virt_to_page((char *)page));
for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk)
- asm volatile("clflush %0" : : "m" (*(char *)(page+offset)));
+ clflush((char *)page+offset);
efficeon_private.l1_table[index] = page;
- value = virt_to_gart((unsigned long *)page) | pati | present | index;
+ value = virt_to_phys((unsigned long *)page) | pati | present | index;
pci_write_config_dword(agp_bridge->dev,
EFFICEON_ATTPAGE, value);
@@ -243,34 +250,35 @@ static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int t
if (type != 0 || mem->type != 0)
return -EINVAL;
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
global_cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
last_page = NULL;
for (i = 0; i < count; i++) {
int index = pg_start + i;
- unsigned long insert = mem->memory[i];
+ unsigned long insert = efficeon_mask_memory(mem->pages[i]);
page = (unsigned int *) efficeon_private.l1_table[index >> 10];
if (!page)
continue;
-
+
page += (index & 0x3ff);
*page = insert;
/* clflush is slow, so don't clflush until we have to */
- if ( last_page &&
- ((unsigned long)page^(unsigned long)last_page) & clflush_mask )
- asm volatile("clflush %0" : : "m" (*last_page));
+ if (last_page &&
+ (((unsigned long)page^(unsigned long)last_page) &
+ clflush_mask))
+ clflush(last_page);
last_page = page;
}
if ( last_page )
- asm volatile("clflush %0" : : "m" (*last_page));
+ clflush(last_page);
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -303,7 +311,7 @@ static int efficeon_remove_memory(struct agp_memory * mem, off_t pg_start, int t
}
-static struct agp_bridge_driver efficeon_driver = {
+static const struct agp_bridge_driver efficeon_driver = {
.owner = THIS_MODULE,
.aperture_sizes = efficeon_generic_sizes,
.size_type = LVL2_APER_SIZE,
@@ -322,24 +330,20 @@ static struct agp_bridge_driver efficeon_driver = {
.free_gatt_table = efficeon_free_gatt_table,
.insert_memory = efficeon_insert_memory,
.remove_memory = efficeon_remove_memory,
- .cant_use_aperture = 0, // 1 might be faster?
+ .cant_use_aperture = false, // true might be faster?
// Generic
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-
-static int agp_efficeon_resume(struct pci_dev *pdev)
-{
- printk(KERN_DEBUG PFX "agp_efficeon_resume()\n");
- return efficeon_configure();
-}
-
-static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_efficeon_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
u8 cap_ptr;
@@ -367,28 +371,30 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
bridge->capndx = cap_ptr;
/*
+ * If the device has not been properly setup, the following will catch
+ * the problem and should stop the system from crashing.
+ * 20030610 - hamish@zot.org
+ */
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR PFX "Unable to Enable PCI device\n");
+ agp_put_bridge(bridge);
+ return -ENODEV;
+ }
+
+ /*
* The following fixes the case where the BIOS has "forgotten" to
* provide an address range for the GART.
* 20030610 - hamish@zot.org
*/
r = &pdev->resource[0];
if (!r->start && r->end) {
- if(pci_assign_resource(pdev, 0)) {
+ if (pci_assign_resource(pdev, 0)) {
printk(KERN_ERR PFX "could not assign resource 0\n");
+ agp_put_bridge(bridge);
return -ENODEV;
}
}
- /*
- * If the device has not been properly setup, the following will catch
- * the problem and should stop the system from crashing.
- * 20030610 - hamish@zot.org
- */
- if (pci_enable_device(pdev)) {
- printk(KERN_ERR PFX "Unable to Enable PCI device\n");
- return -ENODEV;
- }
-
/* Fill in the mode register */
if (cap_ptr) {
pci_read_config_dword(pdev,
@@ -400,7 +406,7 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
+static void agp_efficeon_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -408,11 +414,18 @@ static void __devexit agp_efficeon_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
+#ifdef CONFIG_PM
static int agp_efficeon_suspend(struct pci_dev *dev, pm_message_t state)
{
return 0;
}
+static int agp_efficeon_resume(struct pci_dev *pdev)
+{
+ printk(KERN_DEBUG PFX "agp_efficeon_resume()\n");
+ return efficeon_configure();
+}
+#endif
static struct pci_device_id agp_efficeon_pci_table[] = {
{
@@ -433,8 +446,10 @@ static struct pci_driver agp_efficeon_pci_driver = {
.id_table = agp_efficeon_pci_table,
.probe = agp_efficeon_probe,
.remove = agp_efficeon_remove,
+#ifdef CONFIG_PM
.suspend = agp_efficeon_suspend,
.resume = agp_efficeon_resume,
+#endif
};
static int __init agp_efficeon_init(void)
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 97eeb2345b1..b29703324e9 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -31,19 +31,20 @@
#include <linux/module.h>
#include <linux/mman.h>
#include <linux/pci.h>
-#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/agp_backend.h>
#include <linux/agpgart.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include "agp.h"
-static struct agp_front_data agp_fe;
+struct agp_front_data agp_fe;
-static struct agp_memory *agp_find_mem_by_key(int key)
+struct agp_memory *agp_find_mem_by_key(int key)
{
struct agp_memory *curr;
@@ -151,38 +152,15 @@ static void agp_add_seg_to_client(struct agp_client *client,
client->segments = seg;
}
-/* Originally taken from linux/mm/mmap.c from the array
- * protection_map.
- * The original really should be exported to modules, or
- * some routine which does the conversion for you
- */
-
-static const pgprot_t my_protect_map[16] =
-{
- __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,
- __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
-};
-
static pgprot_t agp_convert_mmap_flags(int prot)
{
-#define _trans(x,bit1,bit2) \
-((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0)
-
unsigned long prot_bits;
- pgprot_t temp;
-
- prot_bits = _trans(prot, PROT_READ, VM_READ) |
- _trans(prot, PROT_WRITE, VM_WRITE) |
- _trans(prot, PROT_EXEC, VM_EXEC);
- prot_bits |= VM_SHARED;
-
- temp = my_protect_map[prot_bits & 0x0000000f];
-
- return temp;
+ prot_bits = calc_vm_prot_bits(prot) | VM_SHARED;
+ return vm_get_page_prot(prot_bits);
}
-static int agp_create_segment(struct agp_client *client, struct agp_region *region)
+int agp_create_segment(struct agp_client *client, struct agp_region *region)
{
struct agp_segment_priv **ret_seg;
struct agp_segment_priv *seg;
@@ -234,7 +212,7 @@ static void agp_insert_into_pool(struct agp_memory * temp)
/* File private list routines */
-static struct agp_file_private *agp_find_private(pid_t pid)
+struct agp_file_private *agp_find_private(pid_t pid)
{
struct agp_file_private *curr;
@@ -289,13 +267,13 @@ static void agp_remove_file_private(struct agp_file_private * priv)
* Wrappers for agp_free_memory & agp_allocate_memory
* These make sure that internal lists are kept updated.
*/
-static void agp_free_memory_wrap(struct agp_memory *memory)
+void agp_free_memory_wrap(struct agp_memory *memory)
{
agp_remove_from_pool(memory);
agp_free_memory(memory);
}
-static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
+struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
{
struct agp_memory *memory;
@@ -416,7 +394,7 @@ static int agp_remove_controller(struct agp_controller *controller)
if (agp_fe.current_controller == controller) {
agp_fe.current_controller = NULL;
- agp_fe.backend_acquired = FALSE;
+ agp_fe.backend_acquired = false;
agp_backend_release(agp_bridge);
}
kfree(controller);
@@ -464,7 +442,7 @@ static void agp_controller_release_current(struct agp_controller *controller,
}
agp_fe.current_controller = NULL;
- agp_fe.used_by_controller = FALSE;
+ agp_fe.used_by_controller = false;
agp_backend_release(agp_bridge);
}
@@ -507,7 +485,7 @@ static struct agp_controller *agp_find_controller_for_client(pid_t id)
return NULL;
}
-static struct agp_client *agp_find_client_by_pid(pid_t id)
+struct agp_client *agp_find_client_by_pid(pid_t id)
{
struct agp_client *temp;
@@ -532,7 +510,7 @@ static void agp_insert_client(struct agp_client *client)
agp_fe.current_controller->num_clients++;
}
-static struct agp_client *agp_create_client(pid_t id)
+struct agp_client *agp_create_client(pid_t id)
{
struct agp_client *new_client;
@@ -545,7 +523,7 @@ static struct agp_client *agp_create_client(pid_t id)
return new_client;
}
-static int agp_remove_client(pid_t id)
+int agp_remove_client(pid_t id)
{
struct agp_client *client;
struct agp_client *prev_client;
@@ -594,7 +572,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
mutex_lock(&(agp_fe.agp_mutex));
- if (agp_fe.backend_acquired != TRUE)
+ if (agp_fe.backend_acquired != true)
goto out_eperm;
if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
@@ -624,7 +602,8 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_ops = kerninfo.vm_ops;
} else if (io_remap_pfn_range(vma, vma->vm_start,
(kerninfo.aper_base + offset) >> PAGE_SHIFT,
- size, vma->vm_page_prot)) {
+ size,
+ pgprot_writecombine(vma->vm_page_prot))) {
goto out_again;
}
mutex_unlock(&(agp_fe.agp_mutex));
@@ -639,8 +618,9 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
if (kerninfo.vm_ops) {
vma->vm_ops = kerninfo.vm_ops;
} else if (io_remap_pfn_range(vma, vma->vm_start,
- kerninfo.aper_base >> PAGE_SHIFT,
- size, vma->vm_page_prot)) {
+ kerninfo.aper_base >> PAGE_SHIFT,
+ size,
+ pgprot_writecombine(vma->vm_page_prot))) {
goto out_again;
}
mutex_unlock(&(agp_fe.agp_mutex));
@@ -696,24 +676,25 @@ static int agp_open(struct inode *inode, struct file *file)
int minor = iminor(inode);
struct agp_file_private *priv;
struct agp_client *client;
- int rc = -ENXIO;
-
- mutex_lock(&(agp_fe.agp_mutex));
if (minor != AGPGART_MINOR)
- goto err_out;
+ return -ENXIO;
+
+ mutex_lock(&(agp_fe.agp_mutex));
priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL);
- if (priv == NULL)
- goto err_out_nomem;
+ if (priv == NULL) {
+ mutex_unlock(&(agp_fe.agp_mutex));
+ return -ENOMEM;
+ }
set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
priv->my_pid = current->pid;
- if ((current->uid == 0) || (current->suid == 0)) {
+ if (capable(CAP_SYS_RAWIO))
/* Root priv, can be controller */
set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
- }
+
client = agp_find_client_by_pid(current->pid);
if (client != NULL) {
@@ -723,14 +704,10 @@ static int agp_open(struct inode *inode, struct file *file)
file->private_data = (void *) priv;
agp_insert_file_private(priv);
DBG("private=%p, client=%p", priv, client);
- mutex_unlock(&(agp_fe.agp_mutex));
- return 0;
-err_out_nomem:
- rc = -ENOMEM;
-err_out:
mutex_unlock(&(agp_fe.agp_mutex));
- return rc;
+
+ return 0;
}
@@ -753,6 +730,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
agp_copy_info(agp_bridge, &kerninfo);
+ memset(&userinfo, 0, sizeof(userinfo));
userinfo.version.major = kerninfo.version.major;
userinfo.version.minor = kerninfo.version.minor;
userinfo.bridge_id = kerninfo.device->vendor |
@@ -769,7 +747,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
return 0;
}
-static int agpioc_acquire_wrap(struct agp_file_private *priv)
+int agpioc_acquire_wrap(struct agp_file_private *priv)
{
struct agp_controller *controller;
@@ -781,7 +759,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
if (agp_fe.current_controller != NULL)
return -EBUSY;
- if(!agp_bridge)
+ if (!agp_bridge)
return -ENODEV;
if (atomic_read(&agp_bridge->agp_in_use))
@@ -789,7 +767,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
atomic_inc(&agp_bridge->agp_in_use);
- agp_fe.backend_acquired = TRUE;
+ agp_fe.backend_acquired = true;
controller = agp_find_controller_by_pid(priv->my_pid);
@@ -799,7 +777,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
controller = agp_create_controller(priv->my_pid);
if (controller == NULL) {
- agp_fe.backend_acquired = FALSE;
+ agp_fe.backend_acquired = false;
agp_backend_release(agp_bridge);
return -ENOMEM;
}
@@ -812,14 +790,14 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
return 0;
}
-static int agpioc_release_wrap(struct agp_file_private *priv)
+int agpioc_release_wrap(struct agp_file_private *priv)
{
DBG("");
agp_controller_release_current(agp_fe.current_controller, priv);
return 0;
}
-static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
+int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
{
struct agp_setup mode;
@@ -899,7 +877,7 @@ static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg)
return -EINVAL;
}
-static int agpioc_protect_wrap(struct agp_file_private *priv)
+int agpioc_protect_wrap(struct agp_file_private *priv)
{
DBG("");
/* This function is not currently implemented */
@@ -915,6 +893,9 @@ static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate)))
return -EFAULT;
+ if (alloc.type >= AGP_USER_TYPES)
+ return -EINVAL;
+
memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type);
if (memory == NULL)
@@ -930,7 +911,7 @@ static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg)
return 0;
}
-static int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
+int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg)
{
struct agp_memory *memory;
@@ -978,7 +959,7 @@ static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
return agp_unbind_memory(memory);
}
-static int agp_ioctl(struct inode *inode, struct file *file,
+static long agp_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct agp_file_private *curr_priv = file->private_data;
@@ -992,7 +973,7 @@ static int agp_ioctl(struct inode *inode, struct file *file,
ret_val = -EINVAL;
goto ioctl_out;
}
- if ((agp_fe.backend_acquired != TRUE) &&
+ if ((agp_fe.backend_acquired != true) &&
(cmd != AGPIOC_ACQUIRE)) {
ret_val = -EBUSY;
goto ioctl_out;
@@ -1051,6 +1032,9 @@ static int agp_ioctl(struct inode *inode, struct file *file,
case AGPIOC_UNBIND:
ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
break;
+
+ case AGPIOC_CHIPSET_FLUSH:
+ break;
}
ioctl_out:
@@ -1059,13 +1043,16 @@ ioctl_out:
return ret_val;
}
-static struct file_operations agp_fops =
+static const struct file_operations agp_fops =
{
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = agp_read,
.write = agp_write,
- .ioctl = agp_ioctl,
+ .unlocked_ioctl = agp_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = compat_agp_ioctl,
+#endif
.mmap = agp_mmap,
.open = agp_open,
.release = agp_release,
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 5567ce8d72b..0fbccce1cee 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -27,10 +27,8 @@
* TODO:
* - Allocate more than order 0 pages to avoid too much linear map splitting.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/miscdevice.h>
#include <linux/pm.h>
@@ -38,6 +36,8 @@
#include <linux/vmalloc.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
@@ -52,28 +52,6 @@ int agp_memory_reserved;
*/
EXPORT_SYMBOL_GPL(agp_memory_reserved);
-#if defined(CONFIG_X86)
-int map_page_into_agp(struct page *page)
-{
- int i;
- i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE);
- /* Caller's responsibility to call global_flush_tlb() for
- * performance reasons */
- return i;
-}
-EXPORT_SYMBOL_GPL(map_page_into_agp);
-
-int unmap_page_from_agp(struct page *page)
-{
- int i;
- i = change_page_attr(page, 1, PAGE_KERNEL);
- /* Caller's responsibility to call global_flush_tlb() for
- * performance reasons */
- return i;
-}
-EXPORT_SYMBOL_GPL(unmap_page_from_agp);
-#endif
-
/*
* Generic routines for handling agp_memory structures -
* They use the basic page allocation routines to do the brunt of the work.
@@ -102,6 +80,64 @@ static int agp_get_key(void)
return -1;
}
+/*
+ * Use kmalloc if possible for the page list. Otherwise fall back to
+ * vmalloc. This speeds things up and also saves memory for small AGP
+ * regions.
+ */
+
+void agp_alloc_page_array(size_t size, struct agp_memory *mem)
+{
+ mem->pages = NULL;
+
+ if (size <= 2*PAGE_SIZE)
+ mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
+ if (mem->pages == NULL) {
+ mem->pages = vmalloc(size);
+ }
+}
+EXPORT_SYMBOL(agp_alloc_page_array);
+
+void agp_free_page_array(struct agp_memory *mem)
+{
+ if (is_vmalloc_addr(mem->pages)) {
+ vfree(mem->pages);
+ } else {
+ kfree(mem->pages);
+ }
+}
+EXPORT_SYMBOL(agp_free_page_array);
+
+
+static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages)
+{
+ struct agp_memory *new;
+ unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
+
+ if (INT_MAX/sizeof(struct page *) < num_agp_pages)
+ return NULL;
+
+ new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
+ if (new == NULL)
+ return NULL;
+
+ new->key = agp_get_key();
+
+ if (new->key < 0) {
+ kfree(new);
+ return NULL;
+ }
+
+ agp_alloc_page_array(alloc_size, new);
+
+ if (new->pages == NULL) {
+ agp_free_key(new->key);
+ kfree(new);
+ return NULL;
+ }
+ new->num_scratch_pages = 0;
+ return new;
+}
struct agp_memory *agp_create_memory(int scratch_pages)
{
@@ -117,14 +153,16 @@ struct agp_memory *agp_create_memory(int scratch_pages)
kfree(new);
return NULL;
}
- new->memory = vmalloc(PAGE_SIZE * scratch_pages);
- if (new->memory == NULL) {
+ agp_alloc_page_array(PAGE_SIZE * scratch_pages, new);
+
+ if (new->pages == NULL) {
agp_free_key(new->key);
kfree(new);
return NULL;
}
new->num_scratch_pages = scratch_pages;
+ new->type = AGP_NORMAL_MEMORY;
return new;
}
EXPORT_SYMBOL(agp_create_memory);
@@ -144,21 +182,37 @@ void agp_free_memory(struct agp_memory *curr)
if (curr == NULL)
return;
- if (curr->is_bound == TRUE)
+ if (curr->is_bound)
agp_unbind_memory(curr);
+ if (curr->type >= AGP_USER_TYPES) {
+ agp_generic_free_by_type(curr);
+ return;
+ }
+
if (curr->type != 0) {
curr->bridge->driver->free_by_type(curr);
return;
}
if (curr->page_count != 0) {
- for (i = 0; i < curr->page_count; i++) {
- curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));
+ if (curr->bridge->driver->agp_destroy_pages) {
+ curr->bridge->driver->agp_destroy_pages(curr);
+ } else {
+
+ for (i = 0; i < curr->page_count; i++) {
+ curr->bridge->driver->agp_destroy_page(
+ curr->pages[i],
+ AGP_PAGE_DESTROY_UNMAP);
+ }
+ for (i = 0; i < curr->page_count; i++) {
+ curr->bridge->driver->agp_destroy_page(
+ curr->pages[i],
+ AGP_PAGE_DESTROY_FREE);
+ }
}
- flush_agp_mappings();
}
agp_free_key(curr->key);
- vfree(curr->memory);
+ agp_free_page_array(curr);
kfree(curr);
}
EXPORT_SYMBOL(agp_free_memory);
@@ -182,13 +236,23 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
int scratch_pages;
struct agp_memory *new;
size_t i;
+ int cur_memory;
if (!bridge)
return NULL;
- if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
+ cur_memory = atomic_read(&bridge->current_memory_agp);
+ if ((cur_memory + page_count > bridge->max_memory_agp) ||
+ (cur_memory + page_count < page_count))
return NULL;
+ if (type >= AGP_USER_TYPES) {
+ new = agp_generic_alloc_user(page_count, type);
+ if (new)
+ new->bridge = bridge;
+ return new;
+ }
+
if (type != 0) {
new = bridge->driver->alloc_by_type(page_count, type);
if (new)
@@ -203,20 +267,27 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
if (new == NULL)
return NULL;
+ if (bridge->driver->agp_alloc_pages) {
+ if (bridge->driver->agp_alloc_pages(bridge, new, page_count)) {
+ agp_free_memory(new);
+ return NULL;
+ }
+ new->bridge = bridge;
+ return new;
+ }
+
for (i = 0; i < page_count; i++) {
- void *addr = bridge->driver->agp_alloc_page(bridge);
+ struct page *page = bridge->driver->agp_alloc_page(bridge);
- if (addr == NULL) {
+ if (page == NULL) {
agp_free_memory(new);
return NULL;
}
- new->memory[i] = virt_to_gart(addr);
+ new->pages[i] = page;
new->page_count++;
}
new->bridge = bridge;
- flush_agp_mappings();
-
return new;
}
EXPORT_SYMBOL(agp_allocate_memory);
@@ -299,7 +370,7 @@ EXPORT_SYMBOL_GPL(agp_num_entries);
/**
* agp_copy_info - copy bridge state information
*
- * @info: agp_kern_info pointer. The caller should insure that this pointer is valid.
+ * @info: agp_kern_info pointer. The caller should insure that this pointer is valid.
*
* This function copies information about the agp bridge device and the state of
* the agp backend into an agp_kern_info pointer.
@@ -355,21 +426,26 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
if (curr == NULL)
return -EINVAL;
- if (curr->is_bound == TRUE) {
+ if (curr->is_bound) {
printk(KERN_INFO PFX "memory %p is already bound!\n", curr);
return -EINVAL;
}
- if (curr->is_flushed == FALSE) {
+ if (!curr->is_flushed) {
curr->bridge->driver->cache_flush();
- curr->is_flushed = TRUE;
+ curr->is_flushed = true;
}
+
ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
if (ret_val != 0)
return ret_val;
- curr->is_bound = TRUE;
+ curr->is_bound = true;
curr->pg_start = pg_start;
+ spin_lock(&agp_bridge->mapped_lock);
+ list_add(&curr->mapped_list, &agp_bridge->mapped_list);
+ spin_unlock(&agp_bridge->mapped_lock);
+
return 0;
}
EXPORT_SYMBOL(agp_bind_memory);
@@ -390,7 +466,7 @@ int agp_unbind_memory(struct agp_memory *curr)
if (curr == NULL)
return -EINVAL;
- if (curr->is_bound != TRUE) {
+ if (!curr->is_bound) {
printk(KERN_INFO PFX "memory %p was not bound!\n", curr);
return -EINVAL;
}
@@ -400,12 +476,16 @@ int agp_unbind_memory(struct agp_memory *curr)
if (ret_val != 0)
return ret_val;
- curr->is_bound = FALSE;
+ curr->is_bound = false;
curr->pg_start = 0;
+ spin_lock(&curr->bridge->mapped_lock);
+ list_del(&curr->mapped_list);
+ spin_unlock(&curr->bridge->mapped_lock);
return 0;
}
EXPORT_SYMBOL(agp_unbind_memory);
+
/* End - Routines for handling swapping of agp_memory into the GATT */
@@ -420,6 +500,31 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
*requested_mode &= ~AGP2_RESERVED_MASK;
}
+ /*
+ * Some dumb bridges are programmed to disobey the AGP2 spec.
+ * This is likely a BIOS misprogramming rather than poweron default, or
+ * it would be a lot more common.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=8816
+ * AGPv2 spec 6.1.9 states:
+ * The RATE field indicates the data transfer rates supported by this
+ * device. A.G.P. devices must report all that apply.
+ * Fix them up as best we can.
+ */
+ switch (*bridge_agpstat & 7) {
+ case 4:
+ *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X);
+ printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate. "
+ "Fixing up support for x2 & x1\n");
+ break;
+ case 2:
+ *bridge_agpstat |= AGPSTAT2_1X;
+ printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate. "
+ "Fixing up support for x1\n");
+ break;
+ default:
+ break;
+ }
+
/* Check the speed bits make sense. Only one should be set. */
tmp = *requested_mode & 7;
switch (tmp) {
@@ -569,25 +674,37 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_
*bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
goto done;
+ } else if (*requested_mode & AGPSTAT3_4X) {
+ *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+ *bridge_agpstat |= AGPSTAT3_4X;
+ goto done;
+
} else {
/*
- * If we didn't specify AGPx8, we can only do x4.
- * If the hardware can't do x4, we're up shit creek, and never
- * should have got this far.
+ * If we didn't specify an AGP mode, we see if both
+ * the graphics card, and the bridge can do x8, and use if so.
+ * If not, we fall back to x4 mode.
*/
- *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
- if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
- *bridge_agpstat |= AGPSTAT3_4X;
- else {
- printk(KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
- "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
- origbridge, origvga, *bridge_agpstat, *vga_agpstat);
- if (!(*bridge_agpstat & AGPSTAT3_4X))
- printk(KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
- if (!(*vga_agpstat & AGPSTAT3_4X))
- printk(KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
- return;
+ if ((*bridge_agpstat & AGPSTAT3_8X) && (*vga_agpstat & AGPSTAT3_8X)) {
+ printk(KERN_INFO PFX "No AGP mode specified. Setting to highest mode "
+ "supported by bridge & card (x8).\n");
+ *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
+ *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
+ } else {
+ printk(KERN_INFO PFX "Fell back to AGPx4 mode because ");
+ if (!(*bridge_agpstat & AGPSTAT3_8X)) {
+ printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n",
+ *bridge_agpstat, origbridge);
+ *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+ *bridge_agpstat |= AGPSTAT3_4X;
+ }
+ if (!(*vga_agpstat & AGPSTAT3_8X)) {
+ printk(KERN_INFO PFX "graphics card couldn't do x8. vga_agpstat:%x (orig=%x)\n",
+ *vga_agpstat, origvga);
+ *vga_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+ *vga_agpstat |= AGPSTAT3_4X;
+ }
}
}
@@ -661,7 +778,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode
EXPORT_SYMBOL(agp_collect_device_status);
-void agp_device_command(u32 bridge_agpstat, int agp_v3)
+void agp_device_command(u32 bridge_agpstat, bool agp_v3)
{
struct pci_dev *device = NULL;
int mode;
@@ -675,8 +792,8 @@ void agp_device_command(u32 bridge_agpstat, int agp_v3)
if (!agp)
continue;
- printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n",
- agp_v3 ? 3 : 2, pci_name(device), mode);
+ dev_info(&device->dev, "putting AGP V%d device into %dx mode\n",
+ agp_v3 ? 3 : 2, mode);
pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat);
}
}
@@ -704,10 +821,8 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
get_agp_version(agp_bridge);
- printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",
- agp_bridge->major_version,
- agp_bridge->minor_version,
- pci_name(agp_bridge->dev));
+ dev_info(&agp_bridge->dev->dev, "AGP %d.%d bridge\n",
+ agp_bridge->major_version, agp_bridge->minor_version);
pci_read_config_dword(agp_bridge->dev,
agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat);
@@ -725,7 +840,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
/* If we have 3.5, we can do the isoch stuff. */
if (bridge->minor_version >= 5)
agp_3_5_enable(bridge);
- agp_device_command(bridge_agpstat, TRUE);
+ agp_device_command(bridge_agpstat, true);
return;
} else {
/* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/
@@ -736,13 +851,12 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
pci_write_config_dword(bridge->dev,
bridge->capndx+AGPCTRL, temp);
- printk(KERN_INFO PFX "Device is in legacy mode,"
- " falling back to 2.x\n");
+ dev_info(&bridge->dev->dev, "bridge is in legacy mode, falling back to 2.x\n");
}
}
/* AGP v<3 */
- agp_device_command(bridge_agpstat, FALSE);
+ agp_device_command(bridge_agpstat, false);
}
EXPORT_SYMBOL(agp_generic_enable);
@@ -809,12 +923,10 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
case U32_APER_SIZE:
bridge->current_size = A_IDX32(bridge);
break;
- /* This case will never really happen. */
+ /* These cases will never really happen. */
case FIXED_APER_SIZE:
case LVL2_APER_SIZE:
default:
- bridge->current_size =
- bridge->current_size;
break;
}
temp = bridge->current_size;
@@ -841,9 +953,16 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
agp_gatt_table = (void *)table;
bridge->driver->cache_flush();
- bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
+#ifdef CONFIG_X86
+ if (set_memory_uc((unsigned long)table, 1 << page_order))
+ printk(KERN_WARNING "Could not set GATT table memory to UC!\n");
+
+ bridge->gatt_table = (u32 __iomem *)table;
+#else
+ bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
(PAGE_SIZE * (1 << page_order)));
bridge->driver->cache_flush();
+#endif
if (bridge->gatt_table == NULL) {
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
@@ -853,7 +972,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
return -ENOMEM;
}
- bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
+ bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
/* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++) {
@@ -890,7 +1009,6 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
case LVL2_APER_SIZE:
/* The generic routines can't deal with 2 level gatt's */
return -EINVAL;
- break;
default:
page_order = 0;
break;
@@ -900,7 +1018,11 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
* called, then all agp memory is deallocated and removed
* from the table. */
+#ifdef CONFIG_X86
+ set_memory_wb((unsigned long)bridge->gatt_table, 1 << page_order);
+#else
iounmap(bridge->gatt_table);
+#endif
table = (char *) bridge->gatt_table_real;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
@@ -926,11 +1048,15 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
off_t j;
void *temp;
struct agp_bridge_data *bridge;
+ int mask_type;
bridge = mem->bridge;
if (!bridge)
return -EINVAL;
+ if (mem->page_count == 0)
+ return 0;
+
temp = bridge->current_size;
switch (bridge->driver->size_type) {
@@ -949,7 +1075,6 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
case LVL2_APER_SIZE:
/* The generic routines can't deal with 2 level gatt's */
return -EINVAL;
- break;
default:
num_entries = 0;
break;
@@ -958,13 +1083,17 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
num_entries -= agp_memory_reserved/PAGE_SIZE;
if (num_entries < 0) num_entries = 0;
- if (type != 0 || mem->type != 0) {
+ if (type != mem->type)
+ return -EINVAL;
+
+ mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+ if (mask_type != 0) {
/* The generic routines know nothing of memory types */
return -EINVAL;
}
- /* AK: could wrap */
- if ((pg_start + mem->page_count) > num_entries)
+ if (((pg_start + mem->page_count) > num_entries) ||
+ ((pg_start + mem->page_count) < pg_start))
return -EINVAL;
j = pg_start;
@@ -975,15 +1104,18 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
j++;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
bridge->driver->cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
- readl(bridge->gatt_table+j); /* PCI Posting. */
+ writel(bridge->driver->mask_memory(bridge,
+ page_to_phys(mem->pages[i]),
+ mask_type),
+ bridge->gatt_table+j);
}
+ readl(bridge->gatt_table+j-1); /* PCI Posting. */
bridge->driver->tlb_flush(mem);
return 0;
@@ -995,12 +1127,25 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
{
size_t i;
struct agp_bridge_data *bridge;
+ int mask_type, num_entries;
bridge = mem->bridge;
if (!bridge)
return -EINVAL;
- if (type != 0 || mem->type != 0) {
+ if (mem->page_count == 0)
+ return 0;
+
+ if (type != mem->type)
+ return -EINVAL;
+
+ num_entries = agp_num_entries();
+ if (((pg_start + mem->page_count) > num_entries) ||
+ ((pg_start + mem->page_count) < pg_start))
+ return -EINVAL;
+
+ mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
+ if (mask_type != 0) {
/* The generic routines know nothing of memory types */
return -EINVAL;
}
@@ -1008,31 +1153,48 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
/* AK: bogus, should encode addresses > 4GB */
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(bridge->scratch_page, bridge->gatt_table+i);
- readl(bridge->gatt_table+i); /* PCI Posting. */
}
+ readl(bridge->gatt_table+i-1); /* PCI Posting. */
- global_cache_flush();
bridge->driver->tlb_flush(mem);
return 0;
}
EXPORT_SYMBOL(agp_generic_remove_memory);
-
struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type)
{
return NULL;
}
EXPORT_SYMBOL(agp_generic_alloc_by_type);
-
void agp_generic_free_by_type(struct agp_memory *curr)
{
- vfree(curr->memory);
+ agp_free_page_array(curr);
agp_free_key(curr->key);
kfree(curr);
}
EXPORT_SYMBOL(agp_generic_free_by_type);
+struct agp_memory *agp_generic_alloc_user(size_t page_count, int type)
+{
+ struct agp_memory *new;
+ int i;
+ int pages;
+
+ pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
+ new = agp_create_user_memory(page_count);
+ if (new == NULL)
+ return NULL;
+
+ for (i = 0; i < page_count; i++)
+ new->pages[i] = NULL;
+ new->page_count = 0;
+ new->type = type;
+ new->num_scratch_pages = pages;
+
+ return new;
+}
+EXPORT_SYMBOL(agp_generic_alloc_user);
/*
* Basic Page Allocation Routines -
@@ -1041,37 +1203,91 @@ EXPORT_SYMBOL(agp_generic_free_by_type);
* against a maximum value.
*/
-void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
+int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *mem, size_t num_pages)
+{
+ struct page * page;
+ int i, ret = -ENOMEM;
+
+ for (i = 0; i < num_pages; i++) {
+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
+ /* agp_free_memory() needs gart address */
+ if (page == NULL)
+ goto out;
+
+#ifndef CONFIG_X86
+ map_page_into_agp(page);
+#endif
+ get_page(page);
+ atomic_inc(&agp_bridge->current_memory_agp);
+
+ mem->pages[i] = page;
+ mem->page_count++;
+ }
+
+#ifdef CONFIG_X86
+ set_pages_array_uc(mem->pages, num_pages);
+#endif
+ ret = 0;
+out:
+ return ret;
+}
+EXPORT_SYMBOL(agp_generic_alloc_pages);
+
+struct page *agp_generic_alloc_page(struct agp_bridge_data *bridge)
{
struct page * page;
- page = alloc_page(GFP_KERNEL);
+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
if (page == NULL)
return NULL;
map_page_into_agp(page);
get_page(page);
- SetPageLocked(page);
atomic_inc(&agp_bridge->current_memory_agp);
- return page_address(page);
+ return page;
}
EXPORT_SYMBOL(agp_generic_alloc_page);
-
-void agp_generic_destroy_page(void *addr)
+void agp_generic_destroy_pages(struct agp_memory *mem)
{
+ int i;
struct page *page;
- if (addr == NULL)
+ if (!mem)
return;
- page = virt_to_page(addr);
- unmap_page_from_agp(page);
- put_page(page);
- unlock_page(page);
- free_page((unsigned long)addr);
- atomic_dec(&agp_bridge->current_memory_agp);
+#ifdef CONFIG_X86
+ set_pages_array_wb(mem->pages, mem->page_count);
+#endif
+
+ for (i = 0; i < mem->page_count; i++) {
+ page = mem->pages[i];
+
+#ifndef CONFIG_X86
+ unmap_page_from_agp(page);
+#endif
+ put_page(page);
+ __free_page(page);
+ atomic_dec(&agp_bridge->current_memory_agp);
+ mem->pages[i] = NULL;
+ }
+}
+EXPORT_SYMBOL(agp_generic_destroy_pages);
+
+void agp_generic_destroy_page(struct page *page, int flags)
+{
+ if (page == NULL)
+ return;
+
+ if (flags & AGP_PAGE_DESTROY_UNMAP)
+ unmap_page_from_agp(page);
+
+ if (flags & AGP_PAGE_DESTROY_FREE) {
+ put_page(page);
+ __free_page(page);
+ atomic_dec(&agp_bridge->current_memory_agp);
+ }
}
EXPORT_SYMBOL(agp_generic_destroy_page);
@@ -1110,13 +1326,13 @@ static void ipi_handler(void *null)
void global_cache_flush(void)
{
- if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0)
+ if (on_each_cpu(ipi_handler, NULL, 1) != 0)
panic(PFX "timed out waiting for the other CPUs!\n");
}
EXPORT_SYMBOL(global_cache_flush);
unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
- unsigned long addr, int type)
+ dma_addr_t addr, int type)
{
/* memory type is ignored in the generic routine */
if (bridge->driver->masks)
@@ -1126,6 +1342,15 @@ unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
}
EXPORT_SYMBOL(agp_generic_mask_memory);
+int agp_generic_type_to_mask_type(struct agp_bridge_data *bridge,
+ int type)
+{
+ if (type >= AGP_USER_TYPES)
+ return 0;
+ return type;
+}
+EXPORT_SYMBOL(agp_generic_type_to_mask_type);
+
/*
* These functions are implemented according to the AGPv3 spec,
* which covers implementation details that had previously been
@@ -1170,8 +1395,8 @@ int agp3_generic_configure(void)
current_size = A_SIZE_16(agp_bridge->current_size);
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* set aperture size */
pci_write_config_word(agp_bridge->dev, agp_bridge->capndx+AGPAPSIZE, current_size->size_value);
@@ -1192,7 +1417,7 @@ void agp3_generic_cleanup(void)
}
EXPORT_SYMBOL(agp3_generic_cleanup);
-struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] =
+const struct aper_size_info_16 agp3_generic_sizes[AGP_GENERIC_SIZES_ENTRIES] =
{
{4096, 1048576, 10,0x000},
{2048, 524288, 9, 0x800},
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index de5d6d21267..3695773ce7c 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -14,15 +14,13 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
#include <asm/acpi-ext.h>
#include "agp.h"
-#ifndef log2
-#define log2(x) ffz(~(x))
-#endif
-
#define HP_ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */
/* HP ZX1 IOC registers */
@@ -85,8 +83,8 @@ static int __init hp_zx1_ioc_shared(void)
/*
* IOC already configured by sba_iommu module; just use
* its setup. We assume:
- * - IOVA space is 1Gb in size
- * - first 512Mb is IOMMU, second 512Mb is GART
+ * - IOVA space is 1Gb in size
+ * - first 512Mb is IOMMU, second 512Mb is GART
*/
hp->io_tlb_ps = readq(hp->ioc_regs+HP_ZX1_TCNFG);
switch (hp->io_tlb_ps) {
@@ -110,12 +108,12 @@ static int __init hp_zx1_ioc_shared(void)
hp->gart_size = HP_ZX1_GART_SIZE;
hp->gatt_entries = hp->gart_size / hp->io_page_size;
- hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
+ hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
/* Normal case when no AGP device in system */
- hp->gatt = NULL;
+ hp->gatt = NULL;
hp->gatt_entries = 0;
printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
"GART disabled\n");
@@ -221,6 +219,7 @@ hp_zx1_lba_init (u64 hpa)
if (cap != PCI_CAP_ID_AGP) {
printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n",
cap, hp->lba_cap_offset);
+ iounmap(hp->lba_regs);
return -ENODEV;
}
@@ -248,7 +247,7 @@ hp_zx1_configure (void)
agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
if (hp->io_pdir_owner) {
- writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
+ writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
readl(hp->ioc_regs+HP_ZX1_TCNFG);
@@ -256,7 +255,7 @@ hp_zx1_configure (void)
readl(hp->ioc_regs+HP_ZX1_IMASK);
writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
readl(hp->ioc_regs+HP_ZX1_IBASE);
- writel(hp->iova_base|log2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM);
+ writel(hp->iova_base|ilog2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM);
readl(hp->ioc_regs+HP_ZX1_PCOM);
}
@@ -284,7 +283,7 @@ hp_zx1_tlbflush (struct agp_memory *mem)
{
struct _hp_private *hp = &hp_private;
- writeq(hp->gart_base | log2(hp->gart_size), hp->ioc_regs+HP_ZX1_PCOM);
+ writeq(hp->gart_base | ilog2(hp->gart_size), hp->ioc_regs+HP_ZX1_PCOM);
readq(hp->ioc_regs+HP_ZX1_PCOM);
}
@@ -337,7 +336,8 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
off_t j, io_pg_start;
int io_pg_count;
- if (type != 0 || mem->type != 0) {
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
return -EINVAL;
}
@@ -355,21 +355,19 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
j++;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
global_cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
unsigned long paddr;
- paddr = mem->memory[i];
+ paddr = page_to_phys(mem->pages[i]);
for (k = 0;
k < hp->io_pages_per_kpage;
k++, j++, paddr += hp->io_page_size) {
- hp->gatt[j] =
- agp_bridge->driver->mask_memory(agp_bridge,
- paddr, type);
+ hp->gatt[j] = HP_ZX1_PDIR_VALID_BIT | paddr;
}
}
@@ -383,7 +381,8 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
struct _hp_private *hp = &hp_private;
int i, io_pg_start, io_pg_count;
- if (type != 0 || mem->type != 0) {
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
return -EINVAL;
}
@@ -398,8 +397,7 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
}
static unsigned long
-hp_zx1_mask_memory (struct agp_bridge_data *bridge,
- unsigned long addr, int type)
+hp_zx1_mask_memory (struct agp_bridge_data *bridge, dma_addr_t addr, int type)
{
return HP_ZX1_PDIR_VALID_BIT | addr;
}
@@ -419,7 +417,7 @@ hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode)
agp_device_command(command, (mode & AGP8X_MODE) != 0);
}
-struct agp_bridge_driver hp_zx1_driver = {
+const struct agp_bridge_driver hp_zx1_driver = {
.owner = THIS_MODULE,
.size_type = FIXED_APER_SIZE,
.configure = hp_zx1_configure,
@@ -437,8 +435,11 @@ struct agp_bridge_driver hp_zx1_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
- .cant_use_aperture = 1,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
+ .cant_use_aperture = true,
};
static int __init
@@ -478,7 +479,6 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
{
acpi_handle handle, parent;
acpi_status status;
- struct acpi_buffer buffer;
struct acpi_device_info *info;
u64 lba_hpa, sba_hpa, length;
int match;
@@ -490,14 +490,11 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
/* Look for an enclosing IOC scope and find its CSR space */
handle = obj;
do {
- buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_SUCCESS(status)) {
+ status = acpi_get_object_info(handle, &info);
+ if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) {
/* TBD check _CID also */
- info = buffer.pointer;
- info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0';
- match = (strcmp(info->hardware_id.value, "HWP0001") == 0);
- ACPI_MEM_FREE(info);
+ match = (strcmp(info->hardware_id.string, "HWP0001") == 0);
+ kfree(info);
if (match) {
status = hp_acpi_csr_space(handle, &sba_hpa, &length);
if (ACPI_SUCCESS(status))
@@ -514,11 +511,15 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
handle = parent;
} while (ACPI_SUCCESS(status));
+ if (ACPI_FAILURE(status))
+ return AE_OK; /* found no enclosing IOC */
+
if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa))
return AE_OK;
- printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset (ioc=%lx, lba=%lx)\n",
- (char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
+ printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset "
+ "(ioc=%llx, lba=%llx)\n", (char *)context,
+ sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
hp_zx1_gart_found = 1;
return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 8ee19a4a6bc..15b240ea484 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -1,7 +1,7 @@
/*
* For documentation on the i460 AGP interface, see Chapter 7 (AGP Subsystem) of
* the "Intel 460GTX Chipset Software Developer's Manual":
- * http://developer.intel.com/design/itanium/downloads/24870401s.htm
+ * http://www.intel.com/design/archives/itanium/downloads/248704.htm
*/
/*
* 460GX support by Chris Ahna <christopher.j.ahna@intel.com>
@@ -13,6 +13,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/agp_backend.h>
+#include <linux/log2.h>
#include "agp.h"
@@ -59,7 +60,8 @@
*/
#define WR_FLUSH_GATT(index) RD_GATT(index)
-#define log2(x) ffz(~(x))
+static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
+ dma_addr_t addr, int type);
static struct {
void *gatt; /* ioremap'd GATT area */
@@ -75,10 +77,11 @@ static struct {
unsigned long *alloced_map; /* bitmap of kernel-pages in use */
int refcount; /* number of kernel pages using the large page */
u64 paddr; /* physical address of large page */
+ struct page *page; /* page pointer */
} *lp_desc;
} i460;
-static struct aper_size_info_8 i460_sizes[3] =
+static const struct aper_size_info_8 i460_sizes[3] =
{
/*
* The 32GB aperture is only available with a 4M GART page size. Due to the
@@ -148,7 +151,7 @@ static int i460_fetch_size (void)
* values[i].size.
*/
values[i].num_entries = (values[i].size << 8) >> (I460_IO_PAGE_SHIFT - 12);
- values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
+ values[i].page_order = ilog2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT);
}
for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
@@ -249,6 +252,10 @@ static int i460_create_gatt_table (struct agp_bridge_data *bridge)
num_entries = A_SIZE_8(temp)->num_entries;
i460.gatt = ioremap(INTEL_I460_ATTBASE, PAGE_SIZE << page_order);
+ if (!i460.gatt) {
+ printk(KERN_ERR PFX "ioremap failed\n");
+ return -ENOMEM;
+ }
/* These are no good, the should be removed from the agp_bridge strucure... */
agp_bridge->gatt_table_real = NULL;
@@ -291,7 +298,10 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem,
void *temp;
pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n",
- mem, pg_start, type, mem->memory[0]);
+ mem, pg_start, type, page_to_phys(mem->pages[0]));
+
+ if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+ return -EINVAL;
io_pg_start = I460_IOPAGES_PER_KPAGE * pg_start;
@@ -315,10 +325,9 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem,
io_page_size = 1UL << I460_IO_PAGE_SHIFT;
for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
- paddr = mem->memory[i];
+ paddr = page_to_phys(mem->pages[i]);
for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
- WR_GATT(j, agp_bridge->driver->mask_memory(agp_bridge,
- paddr, mem->type));
+ WR_GATT(j, i460_mask_memory(agp_bridge, paddr, mem->type));
}
WR_FLUSH_GATT(j - 1);
return 0;
@@ -358,10 +367,9 @@ static int i460_alloc_large_page (struct lp_desc *lp)
{
unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT;
size_t map_size;
- void *lpage;
- lpage = (void *) __get_free_pages(GFP_KERNEL, order);
- if (!lpage) {
+ lp->page = alloc_pages(GFP_KERNEL, order);
+ if (!lp->page) {
printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n");
return -ENOMEM;
}
@@ -369,12 +377,12 @@ static int i460_alloc_large_page (struct lp_desc *lp)
map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8;
lp->alloced_map = kzalloc(map_size, GFP_KERNEL);
if (!lp->alloced_map) {
- free_pages((unsigned long) lpage, order);
+ __free_pages(lp->page, order);
printk(KERN_ERR PFX "Out of memory, we're in trouble...\n");
return -ENOMEM;
}
- lp->paddr = virt_to_gart(lpage);
+ lp->paddr = page_to_phys(lp->page);
lp->refcount = 0;
atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
return 0;
@@ -385,7 +393,7 @@ static void i460_free_large_page (struct lp_desc *lp)
kfree(lp->alloced_map);
lp->alloced_map = NULL;
- free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+ __free_pages(lp->page, I460_IO_PAGE_SHIFT - PAGE_SHIFT);
atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
}
@@ -396,14 +404,17 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
struct lp_desc *start, *end, *lp;
void *temp;
+ if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
+ return -EINVAL;
+
temp = agp_bridge->current_size;
num_entries = A_SIZE_8(temp)->num_entries;
/* Figure out what pg_start means in terms of our large GART pages */
- start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
- end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
- start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
- end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
+ start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
+ end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
+ start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
+ end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
if (end > i460.lp_desc + num_entries) {
printk(KERN_ERR PFX "Looks like we're out of AGP memory\n");
@@ -430,8 +441,8 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
if (i460_alloc_large_page(lp) < 0)
return -ENOMEM;
pg = lp - i460.lp_desc;
- WR_GATT(pg, agp_bridge->driver->mask_memory(agp_bridge,
- lp->paddr, 0));
+ WR_GATT(pg, i460_mask_memory(agp_bridge,
+ lp->paddr, 0));
WR_FLUSH_GATT(pg);
}
@@ -439,7 +450,7 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
idx++, i++)
{
- mem->memory[i] = lp->paddr + idx*PAGE_SIZE;
+ mem->pages[i] = lp->page;
__set_bit(idx, lp->alloced_map);
++lp->refcount;
}
@@ -454,21 +465,21 @@ static int i460_remove_memory_large_io_page (struct agp_memory *mem,
struct lp_desc *start, *end, *lp;
void *temp;
- temp = agp_bridge->driver->current_size;
+ temp = agp_bridge->current_size;
num_entries = A_SIZE_8(temp)->num_entries;
/* Figure out what pg_start means in terms of our large GART pages */
- start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
- end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
- start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
- end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
+ start = &i460.lp_desc[pg_start / I460_KPAGES_PER_IOPAGE];
+ end = &i460.lp_desc[(pg_start + mem->page_count - 1) / I460_KPAGES_PER_IOPAGE];
+ start_offset = pg_start % I460_KPAGES_PER_IOPAGE;
+ end_offset = (pg_start + mem->page_count - 1) % I460_KPAGES_PER_IOPAGE;
for (i = 0, lp = start; lp <= end; ++lp) {
for (idx = ((lp == start) ? start_offset : 0);
idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE);
idx++, i++)
{
- mem->memory[i] = 0;
+ mem->pages[i] = NULL;
__clear_bit(idx, lp->alloced_map);
--lp->refcount;
}
@@ -512,13 +523,12 @@ static int i460_remove_memory (struct agp_memory *mem,
* Let's just hope nobody counts on the allocated AGP memory being there before bind time
* (I don't think current drivers do)...
*/
-static void *i460_alloc_page (struct agp_bridge_data *bridge)
+static struct page *i460_alloc_page (struct agp_bridge_data *bridge)
{
void *page;
if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
page = agp_generic_alloc_page(agp_bridge);
- global_flush_tlb();
} else
/* Returning NULL would cause problems */
/* AK: really dubious code. */
@@ -526,25 +536,24 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge)
return page;
}
-static void i460_destroy_page (void *page)
+static void i460_destroy_page (struct page *page, int flags)
{
if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
- agp_generic_destroy_page(page);
- global_flush_tlb();
+ agp_generic_destroy_page(page, flags);
}
}
#endif /* I460_LARGE_IO_PAGES */
static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
- unsigned long addr, int type)
+ dma_addr_t addr, int type)
{
/* Make sure the returned address is a valid GATT entry */
return bridge->driver->masks[0].mask
| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12);
}
-struct agp_bridge_driver intel_i460_driver = {
+const struct agp_bridge_driver intel_i460_driver = {
.owner = THIS_MODULE,
.aperture_sizes = i460_sizes,
.size_type = U8_APER_SIZE,
@@ -568,15 +577,18 @@ struct agp_bridge_driver intel_i460_driver = {
.insert_memory = i460_insert_memory_small_io_page,
.remove_memory = i460_remove_memory_small_io_page,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
#endif
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
- .cant_use_aperture = 1,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
+ .cant_use_aperture = true,
};
-static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_intel_i460_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
u8 cap_ptr;
@@ -599,7 +611,7 @@ static int __devinit agp_intel_i460_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_intel_i460_remove(struct pci_dev *pdev)
+static void agp_intel_i460_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -625,7 +637,7 @@ static struct pci_driver agp_intel_i460_pci_driver = {
.name = "agpgart-intel-i460",
.id_table = agp_intel_i460_pci_table,
.probe = agp_intel_i460_probe,
- .remove = __devexit_p(agp_intel_i460_remove),
+ .remove = agp_intel_i460_remove,
};
static int __init agp_intel_i460_init(void)
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 631531fd97a..f9b9ca5d31b 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -2,795 +2,17 @@
* Intel AGPGART routines.
*/
-/*
- * Intel(R) 855GM/852GM and 865G support added by David Dawes
- * <dawes@tungstengraphics.com>.
- *
- * Intel(R) 915G/915GM support added by Alan Hourihane
- * <alanh@tungstengraphics.com>.
- */
-
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/pagemap.h>
#include <linux/agp_backend.h>
+#include <asm/smp.h>
#include "agp.h"
-
-/* Intel 815 register */
-#define INTEL_815_APCONT 0x51
-#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
-
-/* Intel i820 registers */
-#define INTEL_I820_RDCR 0x51
-#define INTEL_I820_ERRSTS 0xc8
-
-/* Intel i840 registers */
-#define INTEL_I840_MCHCFG 0x50
-#define INTEL_I840_ERRSTS 0xc8
-
-/* Intel i850 registers */
-#define INTEL_I850_MCHCFG 0x50
-#define INTEL_I850_ERRSTS 0xc8
-
-/* intel 915G registers */
-#define I915_GMADDR 0x18
-#define I915_MMADDR 0x10
-#define I915_PTEADDR 0x1C
-#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
-#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
-
-
-/* Intel 7505 registers */
-#define INTEL_I7505_APSIZE 0x74
-#define INTEL_I7505_NCAPID 0x60
-#define INTEL_I7505_NISTAT 0x6c
-#define INTEL_I7505_ATTBASE 0x78
-#define INTEL_I7505_ERRSTS 0x42
-#define INTEL_I7505_AGPCTRL 0x70
-#define INTEL_I7505_MCHCFG 0x50
-
-static struct aper_size_info_fixed intel_i810_sizes[] =
-{
- {64, 16384, 4},
- /* The 32M mode still requires a 64k gatt */
- {32, 8192, 4}
-};
-
-#define AGP_DCACHE_MEMORY 1
-#define AGP_PHYS_MEMORY 2
-
-static struct gatt_mask intel_i810_masks[] =
-{
- {.mask = I810_PTE_VALID, .type = 0},
- {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
- {.mask = I810_PTE_VALID, .type = 0}
-};
-
-static struct _intel_i810_private {
- struct pci_dev *i810_dev; /* device one */
- volatile u8 __iomem *registers;
- int num_dcache_entries;
-} intel_i810_private;
-
-static int intel_i810_fetch_size(void)
-{
- u32 smram_miscc;
- struct aper_size_info_fixed *values;
-
- pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc);
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
- if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) {
- printk(KERN_WARNING PFX "i810 is disabled\n");
- return 0;
- }
- if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) {
- agp_bridge->previous_size =
- agp_bridge->current_size = (void *) (values + 1);
- agp_bridge->aperture_size_idx = 1;
- return values[1].size;
- } else {
- agp_bridge->previous_size =
- agp_bridge->current_size = (void *) (values);
- agp_bridge->aperture_size_idx = 0;
- return values[0].size;
- }
-
- return 0;
-}
-
-static int intel_i810_configure(void)
-{
- struct aper_size_info_fixed *current_size;
- u32 temp;
- int i;
-
- current_size = A_SIZE_FIX(agp_bridge->current_size);
-
- pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
- temp &= 0xfff80000;
-
- intel_i810_private.registers = ioremap(temp, 128 * 4096);
- if (!intel_i810_private.registers) {
- printk(KERN_ERR PFX "Unable to remap memory.\n");
- return -ENOMEM;
- }
-
- if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
- & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
- /* This will need to be dynamically assigned */
- printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
- intel_i810_private.num_dcache_entries = 1024;
- }
- pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL);
- readl(intel_i810_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
-
- if (agp_bridge->driver->needs_scratch_page) {
- for (i = 0; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
- }
- }
- global_cache_flush();
- return 0;
-}
-
-static void intel_i810_cleanup(void)
-{
- writel(0, intel_i810_private.registers+I810_PGETBL_CTL);
- readl(intel_i810_private.registers); /* PCI Posting. */
- iounmap(intel_i810_private.registers);
-}
-
-static void intel_i810_tlbflush(struct agp_memory *mem)
-{
- return;
-}
-
-static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
-{
- return;
-}
-
-/* Exists to support ARGB cursors */
-static void *i8xx_alloc_pages(void)
-{
- struct page * page;
-
- page = alloc_pages(GFP_KERNEL, 2);
- if (page == NULL)
- return NULL;
-
- if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
- global_flush_tlb();
- __free_page(page);
- return NULL;
- }
- global_flush_tlb();
- get_page(page);
- SetPageLocked(page);
- atomic_inc(&agp_bridge->current_memory_agp);
- return page_address(page);
-}
-
-static void i8xx_destroy_pages(void *addr)
-{
- struct page *page;
-
- if (addr == NULL)
- return;
-
- page = virt_to_page(addr);
- change_page_attr(page, 4, PAGE_KERNEL);
- global_flush_tlb();
- put_page(page);
- unlock_page(page);
- free_pages((unsigned long)addr, 2);
- atomic_dec(&agp_bridge->current_memory_agp);
-}
-
-static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
- int type)
-{
- int i, j, num_entries;
- void *temp;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_FIX(temp)->num_entries;
-
- if ((pg_start + mem->page_count) > num_entries) {
- return -EINVAL;
- }
- for (j = pg_start; j < (pg_start + mem->page_count); j++) {
- if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
- return -EBUSY;
- }
-
- if (type != 0 || mem->type != 0) {
- if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
- /* special insert */
- global_cache_flush();
- for (i = pg_start; i < (pg_start + mem->page_count); i++) {
- writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
- }
- global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
- return 0;
- }
- if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY))
- goto insert;
- return -EINVAL;
- }
-
-insert:
- global_cache_flush();
- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mem->type),
- intel_i810_private.registers+I810_PTE_BASE+(j*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
- }
- global_cache_flush();
-
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
- int type)
-{
- int i;
-
- for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
- }
-
- global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-/*
- * The i810/i830 requires a physical address to program its mouse
- * pointer into hardware.
- * However the Xserver still writes to it through the agp aperture.
- */
-static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
-{
- struct agp_memory *new;
- void *addr;
-
- if (pg_count != 1 && pg_count != 4)
- return NULL;
-
- switch (pg_count) {
- case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
- global_flush_tlb();
- break;
- case 4:
- /* kludge to get 4 physical pages for ARGB cursor */
- addr = i8xx_alloc_pages();
- break;
- default:
- return NULL;
- }
-
- if (addr == NULL)
- return NULL;
-
- new = agp_create_memory(pg_count);
- if (new == NULL)
- return NULL;
-
- new->memory[0] = virt_to_gart(addr);
- if (pg_count == 4) {
- /* kludge to get 4 physical pages for ARGB cursor */
- new->memory[1] = new->memory[0] + PAGE_SIZE;
- new->memory[2] = new->memory[1] + PAGE_SIZE;
- new->memory[3] = new->memory[2] + PAGE_SIZE;
- }
- new->page_count = pg_count;
- new->num_scratch_pages = pg_count;
- new->type = AGP_PHYS_MEMORY;
- new->physical = new->memory[0];
- return new;
-}
-
-static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
-{
- struct agp_memory *new;
-
- if (type == AGP_DCACHE_MEMORY) {
- if (pg_count != intel_i810_private.num_dcache_entries)
- return NULL;
-
- new = agp_create_memory(1);
- if (new == NULL)
- return NULL;
-
- new->type = AGP_DCACHE_MEMORY;
- new->page_count = pg_count;
- new->num_scratch_pages = 0;
- vfree(new->memory);
- return new;
- }
- if (type == AGP_PHYS_MEMORY)
- return alloc_agpphysmem_i8xx(pg_count, type);
-
- return NULL;
-}
-
-static void intel_i810_free_by_type(struct agp_memory *curr)
-{
- agp_free_key(curr->key);
- if(curr->type == AGP_PHYS_MEMORY) {
- if (curr->page_count == 4)
- i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
- else {
- agp_bridge->driver->agp_destroy_page(
- gart_to_virt(curr->memory[0]));
- global_flush_tlb();
- }
- vfree(curr->memory);
- }
- kfree(curr);
-}
-
-static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
- unsigned long addr, int type)
-{
- /* Type checking must be done elsewhere */
- return addr | bridge->driver->masks[type].mask;
-}
-
-static struct aper_size_info_fixed intel_i830_sizes[] =
-{
- {128, 32768, 5},
- /* The 64M mode still requires a 128k gatt */
- {64, 16384, 5},
- {256, 65536, 6},
-};
-
-static struct _intel_i830_private {
- struct pci_dev *i830_dev; /* device one */
- volatile u8 __iomem *registers;
- volatile u32 __iomem *gtt; /* I915G */
- int gtt_entries;
-} intel_i830_private;
-
-static void intel_i830_init_gtt_entries(void)
-{
- u16 gmch_ctrl;
- int gtt_entries;
- u8 rdct;
- int local = 0;
- static const int ddt[4] = { 0, 16, 32, 64 };
- int size;
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
-
- /* We obtain the size of the GTT, which is also stored (for some
- * reason) at the top of stolen memory. Then we add 4KB to that
- * for the video BIOS popup, which is also stored in there. */
- size = agp_bridge->driver->fetch_size() + 4;
-
- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
- switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
- case I830_GMCH_GMS_STOLEN_512:
- gtt_entries = KB(512) - KB(size);
- break;
- case I830_GMCH_GMS_STOLEN_1024:
- gtt_entries = MB(1) - KB(size);
- break;
- case I830_GMCH_GMS_STOLEN_8192:
- gtt_entries = MB(8) - KB(size);
- break;
- case I830_GMCH_GMS_LOCAL:
- rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
- gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
- MB(ddt[I830_RDRAM_DDT(rdct)]);
- local = 1;
- break;
- default:
- gtt_entries = 0;
- break;
- }
- } else {
- switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
- case I855_GMCH_GMS_STOLEN_1M:
- gtt_entries = MB(1) - KB(size);
- break;
- case I855_GMCH_GMS_STOLEN_4M:
- gtt_entries = MB(4) - KB(size);
- break;
- case I855_GMCH_GMS_STOLEN_8M:
- gtt_entries = MB(8) - KB(size);
- break;
- case I855_GMCH_GMS_STOLEN_16M:
- gtt_entries = MB(16) - KB(size);
- break;
- case I855_GMCH_GMS_STOLEN_32M:
- gtt_entries = MB(32) - KB(size);
- break;
- case I915_GMCH_GMS_STOLEN_48M:
- /* Check it's really I915G */
- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
- gtt_entries = MB(48) - KB(size);
- else
- gtt_entries = 0;
- break;
- case I915_GMCH_GMS_STOLEN_64M:
- /* Check it's really I915G */
- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
- gtt_entries = MB(64) - KB(size);
- else
- gtt_entries = 0;
- default:
- gtt_entries = 0;
- break;
- }
- }
- if (gtt_entries > 0)
- printk(KERN_INFO PFX "Detected %dK %s memory.\n",
- gtt_entries / KB(1), local ? "local" : "stolen");
- else
- printk(KERN_INFO PFX
- "No pre-allocated video memory detected.\n");
- gtt_entries /= KB(4);
-
- intel_i830_private.gtt_entries = gtt_entries;
-}
-
-/* The intel i830 automatically initializes the agp aperture during POST.
- * Use the memory already set aside for in the GTT.
- */
-static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
-{
- int page_order;
- struct aper_size_info_fixed *size;
- int num_entries;
- u32 temp;
-
- size = agp_bridge->current_size;
- page_order = size->page_order;
- num_entries = size->num_entries;
- agp_bridge->gatt_table_real = NULL;
-
- pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
- temp &= 0xfff80000;
-
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
- return -ENOMEM;
-
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
- global_cache_flush(); /* FIXME: ?? */
-
- /* we have to call this as early as possible after the MMIO base address is known */
- intel_i830_init_gtt_entries();
-
- agp_bridge->gatt_table = NULL;
-
- agp_bridge->gatt_bus_addr = temp;
-
- return 0;
-}
-
-/* Return the gatt table to a sane state. Use the top of stolen
- * memory for the GTT.
- */
-static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
-{
- return 0;
-}
-
-static int intel_i830_fetch_size(void)
-{
- u16 gmch_ctrl;
- struct aper_size_info_fixed *values;
-
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
- if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
- agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
- /* 855GM/852GM/865G has 128MB aperture size */
- agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
- agp_bridge->aperture_size_idx = 0;
- return values[0].size;
- }
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
-
- if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
- agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
- agp_bridge->aperture_size_idx = 0;
- return values[0].size;
- } else {
- agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + 1);
- agp_bridge->aperture_size_idx = 1;
- return values[1].size;
- }
-
- return 0;
-}
-
-static int intel_i830_configure(void)
-{
- struct aper_size_info_fixed *current_size;
- u32 temp;
- u16 gmch_ctrl;
- int i;
-
- current_size = A_SIZE_FIX(agp_bridge->current_size);
-
- pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
- gmch_ctrl |= I830_GMCH_ENABLED;
- pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
-
- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
- readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
-
- if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
- }
- }
-
- global_cache_flush();
- return 0;
-}
-
-static void intel_i830_cleanup(void)
-{
- iounmap(intel_i830_private.registers);
-}
-
-static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type)
-{
- int i,j,num_entries;
- void *temp;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_FIX(temp)->num_entries;
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
-
- printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
- return -EINVAL;
- }
-
- if ((pg_start + mem->page_count) > num_entries)
- return -EINVAL;
-
- /* The i830 can't check the GTT for entries since its read only,
- * depend on the caller to make the correct offset decisions.
- */
-
- if ((type != 0 && type != AGP_PHYS_MEMORY) ||
- (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
- return -EINVAL;
-
- global_cache_flush(); /* FIXME: Necessary ?*/
-
- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mem->type),
- intel_i830_private.registers+I810_PTE_BASE+(j*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
- }
-
- global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
- int type)
-{
- int i;
-
- global_cache_flush();
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
- return -EINVAL;
- }
-
- for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
- }
-
- global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
-{
- if (type == AGP_PHYS_MEMORY)
- return alloc_agpphysmem_i8xx(pg_count, type);
-
- /* always return NULL for other allocation types for now */
- return NULL;
-}
-
-static int intel_i915_configure(void)
-{
- struct aper_size_info_fixed *current_size;
- u32 temp;
- u16 gmch_ctrl;
- int i;
-
- current_size = A_SIZE_FIX(agp_bridge->current_size);
-
- pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
-
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
- gmch_ctrl |= I830_GMCH_ENABLED;
- pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
-
- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
- readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
-
- if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
- readl(intel_i830_private.gtt+i); /* PCI Posting. */
- }
- }
-
- global_cache_flush();
- return 0;
-}
-
-static void intel_i915_cleanup(void)
-{
- iounmap(intel_i830_private.gtt);
- iounmap(intel_i830_private.registers);
-}
-
-static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
- int type)
-{
- int i,j,num_entries;
- void *temp;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_FIX(temp)->num_entries;
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
-
- printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
- return -EINVAL;
- }
-
- if ((pg_start + mem->page_count) > num_entries)
- return -EINVAL;
-
- /* The i830 can't check the GTT for entries since its read only,
- * depend on the caller to make the correct offset decisions.
- */
-
- if ((type != 0 && type != AGP_PHYS_MEMORY) ||
- (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
- return -EINVAL;
-
- global_cache_flush();
-
- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mem->type), intel_i830_private.gtt+j);
- readl(intel_i830_private.gtt+j); /* PCI Posting. */
- }
-
- global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
- int type)
-{
- int i;
-
- global_cache_flush();
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
- return -EINVAL;
- }
-
- for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
- readl(intel_i830_private.gtt+i);
- }
-
- global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static int intel_i915_fetch_size(void)
-{
- struct aper_size_info_fixed *values;
- u32 temp, offset = 0;
-
-#define I915_256MB_ADDRESS_MASK (1<<27)
-
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
- pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
- if (temp & I915_256MB_ADDRESS_MASK)
- offset = 0; /* 128MB aperture */
- else
- offset = 2; /* 256MB aperture */
- agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
- return values[offset].size;
-}
-
-/* The intel i915 automatically initializes the agp aperture during POST.
- * Use the memory already set aside for in the GTT.
- */
-static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
-{
- int page_order;
- struct aper_size_info_fixed *size;
- int num_entries;
- u32 temp, temp2;
-
- size = agp_bridge->current_size;
- page_order = size->page_order;
- num_entries = size->num_entries;
- agp_bridge->gatt_table_real = NULL;
-
- pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
- pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
-
- intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
- if (!intel_i830_private.gtt)
- return -ENOMEM;
-
- temp &= 0xfff80000;
-
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
- return -ENOMEM;
-
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
- global_cache_flush(); /* FIXME: ? */
-
- /* we have to call this as early as possible after the MMIO base address is known */
- intel_i830_init_gtt_entries();
-
- agp_bridge->gatt_table = NULL;
-
- agp_bridge->gatt_bus_addr = temp;
-
- return 0;
-}
+#include "intel-agp.h"
+#include <drm/intel-gtt.h>
static int intel_fetch_size(void)
{
@@ -893,7 +115,6 @@ static void intel_8xx_cleanup(void)
static int intel_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_16 *current_size;
@@ -903,8 +124,8 @@ static int intel_configure(void)
pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -923,7 +144,7 @@ static int intel_configure(void)
static int intel_815_configure(void)
{
- u32 temp, addr;
+ u32 addr;
u8 temp2;
struct aper_size_info_8 *current_size;
@@ -931,7 +152,7 @@ static int intel_815_configure(void)
/* the Intel 815 chipset spec. says that bits 29-31 in the
* ATTBASE register are reserved -> try not to write them */
if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
- printk (KERN_EMERG PFX "gatt bus addr too high");
+ dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high");
return -EINVAL;
}
@@ -942,8 +163,8 @@ static int intel_815_configure(void)
current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
pci_read_config_dword(agp_bridge->dev, INTEL_ATTBASE, &addr);
addr &= INTEL_815_ATTBASE_MASK;
@@ -983,7 +204,6 @@ static void intel_820_cleanup(void)
static int intel_820_configure(void)
{
- u32 temp;
u8 temp2;
struct aper_size_info_8 *current_size;
@@ -993,8 +213,8 @@ static int intel_820_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -1014,7 +234,6 @@ static int intel_820_configure(void)
static int intel_840_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;
@@ -1024,8 +243,8 @@ static int intel_840_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -1043,7 +262,6 @@ static int intel_840_configure(void)
static int intel_845_configure(void)
{
- u32 temp;
u8 temp2;
struct aper_size_info_8 *current_size;
@@ -1057,9 +275,9 @@ static int intel_845_configure(void)
agp_bridge->apbase_config);
} else {
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- agp_bridge->apbase_config = temp;
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
+ agp_bridge->apbase_config = agp_bridge->gart_bus_addr;
}
/* attbase - aperture base */
@@ -1078,7 +296,6 @@ static int intel_845_configure(void)
static int intel_850_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;
@@ -1088,8 +305,8 @@ static int intel_850_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -1107,7 +324,6 @@ static int intel_850_configure(void)
static int intel_860_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;
@@ -1117,8 +333,8 @@ static int intel_860_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -1136,7 +352,6 @@ static int intel_860_configure(void)
static int intel_830mp_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;
@@ -1146,8 +361,8 @@ static int intel_830mp_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -1165,7 +380,6 @@ static int intel_830mp_configure(void)
static int intel_7505_configure(void)
{
- u32 temp;
u16 temp2;
struct aper_size_info_8 *current_size;
@@ -1175,8 +389,8 @@ static int intel_7505_configure(void)
pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
/* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture base */
pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
@@ -1192,18 +406,18 @@ static int intel_7505_configure(void)
}
/* Setup function */
-static struct gatt_mask intel_generic_masks[] =
+static const struct gatt_mask intel_generic_masks[] =
{
{.mask = 0x00000017, .type = 0}
};
-static struct aper_size_info_8 intel_815_sizes[2] =
+static const struct aper_size_info_8 intel_815_sizes[2] =
{
{64, 16384, 4, 0},
{32, 8192, 3, 8},
};
-static struct aper_size_info_8 intel_8xx_sizes[7] =
+static const struct aper_size_info_8 intel_8xx_sizes[7] =
{
{256, 65536, 6, 0},
{128, 32768, 5, 32},
@@ -1214,7 +428,7 @@ static struct aper_size_info_8 intel_8xx_sizes[7] =
{4, 1024, 0, 63}
};
-static struct aper_size_info_16 intel_generic_sizes[7] =
+static const struct aper_size_info_16 intel_generic_sizes[7] =
{
{256, 65536, 6, 0},
{128, 32768, 5, 32},
@@ -1225,7 +439,7 @@ static struct aper_size_info_16 intel_generic_sizes[7] =
{4, 1024, 0, 63}
};
-static struct aper_size_info_8 intel_830mp_sizes[4] =
+static const struct aper_size_info_8 intel_830mp_sizes[4] =
{
{256, 65536, 6, 0},
{128, 32768, 5, 32},
@@ -1233,11 +447,12 @@ static struct aper_size_info_8 intel_830mp_sizes[4] =
{32, 8192, 3, 56}
};
-static struct agp_bridge_driver intel_generic_driver = {
+static const struct agp_bridge_driver intel_generic_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_generic_sizes,
.size_type = U16_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = intel_configure,
.fetch_size = intel_fetch_size,
.cleanup = intel_cleanup,
@@ -1253,38 +468,18 @@ static struct agp_bridge_driver intel_generic_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_810_driver = {
- .owner = THIS_MODULE,
- .aperture_sizes = intel_i810_sizes,
- .size_type = FIXED_APER_SIZE,
- .num_aperture_sizes = 2,
- .needs_scratch_page = TRUE,
- .configure = intel_i810_configure,
- .fetch_size = intel_i810_fetch_size,
- .cleanup = intel_i810_cleanup,
- .tlb_flush = intel_i810_tlbflush,
- .mask_memory = intel_i810_mask_memory,
- .masks = intel_i810_masks,
- .agp_enable = intel_i810_agp_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = agp_generic_create_gatt_table,
- .free_gatt_table = agp_generic_free_gatt_table,
- .insert_memory = intel_i810_insert_entries,
- .remove_memory = intel_i810_remove_entries,
- .alloc_by_type = intel_i810_alloc_by_type,
- .free_by_type = intel_i810_free_by_type,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_destroy_page = agp_generic_destroy_page,
-};
-
-static struct agp_bridge_driver intel_815_driver = {
+static const struct agp_bridge_driver intel_815_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_815_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 2,
+ .needs_scratch_page = true,
.configure = intel_815_configure,
.fetch_size = intel_815_fetch_size,
.cleanup = intel_8xx_cleanup,
@@ -1300,38 +495,18 @@ static struct agp_bridge_driver intel_815_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_830_driver = {
- .owner = THIS_MODULE,
- .aperture_sizes = intel_i830_sizes,
- .size_type = FIXED_APER_SIZE,
- .num_aperture_sizes = 3,
- .needs_scratch_page = TRUE,
- .configure = intel_i830_configure,
- .fetch_size = intel_i830_fetch_size,
- .cleanup = intel_i830_cleanup,
- .tlb_flush = intel_i810_tlbflush,
- .mask_memory = intel_i810_mask_memory,
- .masks = intel_i810_masks,
- .agp_enable = intel_i810_agp_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = intel_i830_create_gatt_table,
- .free_gatt_table = intel_i830_free_gatt_table,
- .insert_memory = intel_i830_insert_entries,
- .remove_memory = intel_i830_remove_entries,
- .alloc_by_type = intel_i830_alloc_by_type,
- .free_by_type = intel_i810_free_by_type,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_destroy_page = agp_generic_destroy_page,
-};
-
-static struct agp_bridge_driver intel_820_driver = {
+static const struct agp_bridge_driver intel_820_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = intel_820_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_820_cleanup,
@@ -1347,14 +522,18 @@ static struct agp_bridge_driver intel_820_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_830mp_driver = {
+static const struct agp_bridge_driver intel_830mp_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_830mp_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 4,
+ .needs_scratch_page = true,
.configure = intel_830mp_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_8xx_cleanup,
@@ -1370,14 +549,18 @@ static struct agp_bridge_driver intel_830mp_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_840_driver = {
+static const struct agp_bridge_driver intel_840_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = intel_840_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_8xx_cleanup,
@@ -1393,14 +576,18 @@ static struct agp_bridge_driver intel_840_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_845_driver = {
+static const struct agp_bridge_driver intel_845_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = intel_845_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_8xx_cleanup,
@@ -1416,14 +603,18 @@ static struct agp_bridge_driver intel_845_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_850_driver = {
+static const struct agp_bridge_driver intel_850_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = intel_850_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_8xx_cleanup,
@@ -1439,14 +630,18 @@ static struct agp_bridge_driver intel_850_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_860_driver = {
+static const struct agp_bridge_driver intel_860_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = intel_860_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_8xx_cleanup,
@@ -1462,39 +657,18 @@ static struct agp_bridge_driver intel_860_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver intel_915_driver = {
- .owner = THIS_MODULE,
- .aperture_sizes = intel_i830_sizes,
- .size_type = FIXED_APER_SIZE,
- .num_aperture_sizes = 3,
- .needs_scratch_page = TRUE,
- .configure = intel_i915_configure,
- .fetch_size = intel_i915_fetch_size,
- .cleanup = intel_i915_cleanup,
- .tlb_flush = intel_i810_tlbflush,
- .mask_memory = intel_i810_mask_memory,
- .masks = intel_i810_masks,
- .agp_enable = intel_i810_agp_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = intel_i915_create_gatt_table,
- .free_gatt_table = intel_i830_free_gatt_table,
- .insert_memory = intel_i915_insert_entries,
- .remove_memory = intel_i915_remove_entries,
- .alloc_by_type = intel_i830_alloc_by_type,
- .free_by_type = intel_i810_free_by_type,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_destroy_page = agp_generic_destroy_page,
-};
-
-
-static struct agp_bridge_driver intel_7505_driver = {
+static const struct agp_bridge_driver intel_7505_driver = {
.owner = THIS_MODULE,
.aperture_sizes = intel_8xx_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = intel_7505_configure,
.fetch_size = intel_8xx_fetch_size,
.cleanup = intel_8xx_cleanup,
@@ -1510,44 +684,50 @@ static struct agp_bridge_driver intel_7505_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static int find_i810(u16 device)
-{
- struct pci_dev *i810_dev;
-
- i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
- if (!i810_dev)
- return 0;
- intel_i810_private.i810_dev = i810_dev;
- return 1;
-}
-
-static int find_i830(u16 device)
-{
- struct pci_dev *i830_dev;
-
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
- if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- device, i830_dev);
- }
-
- if (!i830_dev)
- return 0;
-
- intel_i830_private.i830_dev = i830_dev;
- return 1;
-}
+/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
+ * driver and gmch_driver must be non-null, and find_gmch will determine
+ * which one should be used if a gmch_chip_id is present.
+ */
+static const struct intel_agp_driver_description {
+ unsigned int chip_id;
+ char *name;
+ const struct agp_bridge_driver *driver;
+} intel_agp_chipsets[] = {
+ { PCI_DEVICE_ID_INTEL_82443LX_0, "440LX", &intel_generic_driver },
+ { PCI_DEVICE_ID_INTEL_82443BX_0, "440BX", &intel_generic_driver },
+ { PCI_DEVICE_ID_INTEL_82443GX_0, "440GX", &intel_generic_driver },
+ { PCI_DEVICE_ID_INTEL_82815_MC, "i815", &intel_815_driver },
+ { PCI_DEVICE_ID_INTEL_82820_HB, "i820", &intel_820_driver },
+ { PCI_DEVICE_ID_INTEL_82820_UP_HB, "i820", &intel_820_driver },
+ { PCI_DEVICE_ID_INTEL_82830_HB, "830M", &intel_830mp_driver },
+ { PCI_DEVICE_ID_INTEL_82840_HB, "i840", &intel_840_driver },
+ { PCI_DEVICE_ID_INTEL_82845_HB, "i845", &intel_845_driver },
+ { PCI_DEVICE_ID_INTEL_82845G_HB, "845G", &intel_845_driver },
+ { PCI_DEVICE_ID_INTEL_82850_HB, "i850", &intel_850_driver },
+ { PCI_DEVICE_ID_INTEL_82854_HB, "854", &intel_845_driver },
+ { PCI_DEVICE_ID_INTEL_82855PM_HB, "855PM", &intel_845_driver },
+ { PCI_DEVICE_ID_INTEL_82855GM_HB, "855GM", &intel_845_driver },
+ { PCI_DEVICE_ID_INTEL_82860_HB, "i860", &intel_860_driver },
+ { PCI_DEVICE_ID_INTEL_82865_HB, "865", &intel_845_driver },
+ { PCI_DEVICE_ID_INTEL_82875_HB, "i875", &intel_845_driver },
+ { PCI_DEVICE_ID_INTEL_7505_0, "E7505", &intel_7505_driver },
+ { PCI_DEVICE_ID_INTEL_7205_0, "E7205", &intel_7505_driver },
+ { 0, NULL, NULL }
+};
-static int __devinit agp_intel_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_intel_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
- char *name = "(unknown)";
u8 cap_ptr = 0;
struct resource *r;
+ int i, err;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
@@ -1555,177 +735,48 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
if (!bridge)
return -ENOMEM;
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_82443LX_0:
- bridge->driver = &intel_generic_driver;
- name = "440LX";
- break;
- case PCI_DEVICE_ID_INTEL_82443BX_0:
- bridge->driver = &intel_generic_driver;
- name = "440BX";
- break;
- case PCI_DEVICE_ID_INTEL_82443GX_0:
- bridge->driver = &intel_generic_driver;
- name = "440GX";
- break;
- case PCI_DEVICE_ID_INTEL_82810_MC1:
- name = "i810";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82810_MC3:
- name = "i810 DC100";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82810E_MC:
- name = "i810 E";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82815_MC:
- /*
- * The i815 can operate either as an i810 style
- * integrated device, or as an AGP4X motherboard.
- */
- if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
- bridge->driver = &intel_810_driver;
- else
- bridge->driver = &intel_815_driver;
- name = "i815";
- break;
- case PCI_DEVICE_ID_INTEL_82820_HB:
- case PCI_DEVICE_ID_INTEL_82820_UP_HB:
- bridge->driver = &intel_820_driver;
- name = "i820";
- break;
- case PCI_DEVICE_ID_INTEL_82830_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) {
- bridge->driver = &intel_830_driver;
- } else {
- bridge->driver = &intel_830mp_driver;
- }
- name = "830M";
- break;
- case PCI_DEVICE_ID_INTEL_82840_HB:
- bridge->driver = &intel_840_driver;
- name = "i840";
- break;
- case PCI_DEVICE_ID_INTEL_82845_HB:
- bridge->driver = &intel_845_driver;
- name = "i845";
- break;
- case PCI_DEVICE_ID_INTEL_82845G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) {
- bridge->driver = &intel_830_driver;
- } else {
- bridge->driver = &intel_845_driver;
- }
- name = "845G";
- break;
- case PCI_DEVICE_ID_INTEL_82850_HB:
- bridge->driver = &intel_850_driver;
- name = "i850";
- break;
- case PCI_DEVICE_ID_INTEL_82855PM_HB:
- bridge->driver = &intel_845_driver;
- name = "855PM";
- break;
- case PCI_DEVICE_ID_INTEL_82855GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) {
- bridge->driver = &intel_830_driver;
- name = "855";
- } else {
- bridge->driver = &intel_845_driver;
- name = "855GM";
- }
- break;
- case PCI_DEVICE_ID_INTEL_82860_HB:
- bridge->driver = &intel_860_driver;
- name = "i860";
- break;
- case PCI_DEVICE_ID_INTEL_82865_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
- bridge->driver = &intel_830_driver;
- } else {
- bridge->driver = &intel_845_driver;
- }
- name = "865";
- break;
- case PCI_DEVICE_ID_INTEL_82875_HB:
- bridge->driver = &intel_845_driver;
- name = "i875";
- break;
- case PCI_DEVICE_ID_INTEL_82915G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG)) {
- bridge->driver = &intel_915_driver;
- } else {
- bridge->driver = &intel_845_driver;
- }
- name = "915G";
- break;
- case PCI_DEVICE_ID_INTEL_82915GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG)) {
- bridge->driver = &intel_915_driver;
- } else {
- bridge->driver = &intel_845_driver;
- }
- name = "915GM";
- break;
- case PCI_DEVICE_ID_INTEL_82945G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) {
- bridge->driver = &intel_915_driver;
- } else {
- bridge->driver = &intel_845_driver;
- }
- name = "945G";
- break;
- case PCI_DEVICE_ID_INTEL_82945GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG)) {
- bridge->driver = &intel_915_driver;
- } else {
- bridge->driver = &intel_845_driver;
+ bridge->capndx = cap_ptr;
+
+ if (intel_gmch_probe(pdev, NULL, bridge))
+ goto found_gmch;
+
+ for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
+ /* In case that multiple models of gfx chip may
+ stand on same host bridge type, this can be
+ sure we detect the right IGD. */
+ if (pdev->device == intel_agp_chipsets[i].chip_id) {
+ bridge->driver = intel_agp_chipsets[i].driver;
+ break;
}
- name = "945GM";
- break;
- case PCI_DEVICE_ID_INTEL_7505_0:
- bridge->driver = &intel_7505_driver;
- name = "E7505";
- break;
- case PCI_DEVICE_ID_INTEL_7205_0:
- bridge->driver = &intel_7505_driver;
- name = "E7205";
- break;
- default:
+ }
+
+ if (!bridge->driver) {
if (cap_ptr)
- printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
- pdev->device);
+ dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n",
+ pdev->vendor, pdev->device);
agp_put_bridge(bridge);
return -ENODEV;
- };
+ }
bridge->dev = pdev;
- bridge->capndx = cap_ptr;
-
- if (bridge->driver == &intel_810_driver)
- bridge->dev_private_data = &intel_i810_private;
- else if (bridge->driver == &intel_830_driver)
- bridge->dev_private_data = &intel_i830_private;
+ bridge->dev_private_data = NULL;
- printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
+ dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
/*
* The following fixes the case where the BIOS has "forgotten" to
* provide an address range for the GART.
* 20030610 - hamish@zot.org
+ * This happens before pci_enable_device() intentionally;
+ * calling pci_enable_device() before assigning the resource
+ * will result in the GART being disabled on machines with such
+ * BIOSs (the GART ends up with a BAR starting at 0, which
+ * conflicts a lot of other devices).
*/
r = &pdev->resource[0];
if (!r->start && r->end) {
- if(pci_assign_resource(pdev, 0)) {
- printk(KERN_ERR PFX "could not assign resource 0\n");
+ if (pci_assign_resource(pdev, 0)) {
+ dev_err(&pdev->dev, "can't assign resource 0\n");
agp_put_bridge(bridge);
return -ENODEV;
}
@@ -1737,7 +788,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
* 20030610 - hamish@zot.org
*/
if (pci_enable_device(pdev)) {
- printk(KERN_ERR PFX "Unable to Enable PCI device\n");
+ dev_err(&pdev->dev, "can't enable PCI device\n");
agp_put_bridge(bridge);
return -ENODEV;
}
@@ -1749,53 +800,33 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
&bridge->mode);
}
+found_gmch:
pci_set_drvdata(pdev, bridge);
- return agp_add_bridge(bridge);
-
-fail:
- printk(KERN_ERR PFX "Detected an Intel %s chipset, "
- "but could not find the secondary device.\n", name);
- agp_put_bridge(bridge);
- return -ENODEV;
+ err = agp_add_bridge(bridge);
+ return err;
}
-static void __devexit agp_intel_remove(struct pci_dev *pdev)
+static void agp_intel_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
agp_remove_bridge(bridge);
- if (intel_i810_private.i810_dev)
- pci_dev_put(intel_i810_private.i810_dev);
- if (intel_i830_private.i830_dev)
- pci_dev_put(intel_i830_private.i830_dev);
+ intel_gmch_remove();
agp_put_bridge(bridge);
}
+#ifdef CONFIG_PM
static int agp_intel_resume(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- pci_restore_state(pdev);
-
- if (bridge->driver == &intel_generic_driver)
- intel_configure();
- else if (bridge->driver == &intel_850_driver)
- intel_850_configure();
- else if (bridge->driver == &intel_845_driver)
- intel_845_configure();
- else if (bridge->driver == &intel_830mp_driver)
- intel_830mp_configure();
- else if (bridge->driver == &intel_915_driver)
- intel_i915_configure();
- else if (bridge->driver == &intel_830_driver)
- intel_i830_configure();
- else if (bridge->driver == &intel_810_driver)
- intel_i810_configure();
+ bridge->driver->configure();
return 0;
}
+#endif
static struct pci_device_id agp_intel_pci_table[] = {
#define ID(x) \
@@ -1807,6 +838,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
.subvendor = PCI_ANY_ID, \
.subdevice = PCI_ANY_ID, \
}
+ ID(PCI_DEVICE_ID_INTEL_82441), /* for HAS2 support */
ID(PCI_DEVICE_ID_INTEL_82443LX_0),
ID(PCI_DEVICE_ID_INTEL_82443BX_0),
ID(PCI_DEVICE_ID_INTEL_82443GX_0),
@@ -1821,6 +853,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_82845_HB),
ID(PCI_DEVICE_ID_INTEL_82845G_HB),
ID(PCI_DEVICE_ID_INTEL_82850_HB),
+ ID(PCI_DEVICE_ID_INTEL_82854_HB),
ID(PCI_DEVICE_ID_INTEL_82855PM_HB),
ID(PCI_DEVICE_ID_INTEL_82855GM_HB),
ID(PCI_DEVICE_ID_INTEL_82860_HB),
@@ -1828,10 +861,35 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_82875_HB),
ID(PCI_DEVICE_ID_INTEL_7505_0),
ID(PCI_DEVICE_ID_INTEL_7205_0),
+ ID(PCI_DEVICE_ID_INTEL_E7221_HB),
ID(PCI_DEVICE_ID_INTEL_82915G_HB),
ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
ID(PCI_DEVICE_ID_INTEL_82945G_HB),
ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
+ ID(PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB),
+ ID(PCI_DEVICE_ID_INTEL_PINEVIEW_HB),
+ ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
+ ID(PCI_DEVICE_ID_INTEL_82G35_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965G_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_82965GME_HB),
+ ID(PCI_DEVICE_ID_INTEL_G33_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q35_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q33_HB),
+ ID(PCI_DEVICE_ID_INTEL_GM45_HB),
+ ID(PCI_DEVICE_ID_INTEL_EAGLELAKE_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q45_HB),
+ ID(PCI_DEVICE_ID_INTEL_G45_HB),
+ ID(PCI_DEVICE_ID_INTEL_G41_HB),
+ ID(PCI_DEVICE_ID_INTEL_B43_HB),
+ ID(PCI_DEVICE_ID_INTEL_B43_1_HB),
+ ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
+ ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB),
+ ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
+ ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
+ ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
{ }
};
@@ -1841,8 +899,10 @@ static struct pci_driver agp_intel_pci_driver = {
.name = "agpgart-intel",
.id_table = agp_intel_pci_table,
.probe = agp_intel_probe,
- .remove = __devexit_p(agp_intel_remove),
+ .remove = agp_intel_remove,
+#ifdef CONFIG_PM
.resume = agp_intel_resume,
+#endif
};
static int __init agp_intel_init(void)
@@ -1860,5 +920,5 @@ static void __exit agp_intel_cleanup(void)
module_init(agp_intel_init);
module_exit(agp_intel_cleanup);
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
new file mode 100644
index 00000000000..fda073dcd96
--- /dev/null
+++ b/drivers/char/agp/intel-agp.h
@@ -0,0 +1,193 @@
+/*
+ * Common Intel AGPGART and GTT definitions.
+ */
+#ifndef _INTEL_AGP_H
+#define _INTEL_AGP_H
+
+/* Intel registers */
+#define INTEL_APSIZE 0xb4
+#define INTEL_ATTBASE 0xb8
+#define INTEL_AGPCTRL 0xb0
+#define INTEL_NBXCFG 0x50
+#define INTEL_ERRSTS 0x91
+
+/* Intel i830 registers */
+#define I830_GMCH_CTRL 0x52
+#define I830_GMCH_ENABLED 0x4
+#define I830_GMCH_MEM_MASK 0x1
+#define I830_GMCH_MEM_64M 0x1
+#define I830_GMCH_MEM_128M 0
+#define I830_GMCH_GMS_MASK 0x70
+#define I830_GMCH_GMS_DISABLED 0x00
+#define I830_GMCH_GMS_LOCAL 0x10
+#define I830_GMCH_GMS_STOLEN_512 0x20
+#define I830_GMCH_GMS_STOLEN_1024 0x30
+#define I830_GMCH_GMS_STOLEN_8192 0x40
+#define I830_RDRAM_CHANNEL_TYPE 0x03010
+#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5)
+#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3)
+
+/* This one is for I830MP w. an external graphic card */
+#define INTEL_I830_ERRSTS 0x92
+
+/* Intel 855GM/852GM registers */
+#define I855_GMCH_GMS_MASK 0xF0
+#define I855_GMCH_GMS_STOLEN_0M 0x0
+#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
+#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
+#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4)
+#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4)
+#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4)
+#define I85X_CAPID 0x44
+#define I85X_VARIANT_MASK 0x7
+#define I85X_VARIANT_SHIFT 5
+#define I855_GME 0x0
+#define I855_GM 0x4
+#define I852_GME 0x2
+#define I852_GM 0x5
+
+/* Intel i845 registers */
+#define INTEL_I845_AGPM 0x51
+#define INTEL_I845_ERRSTS 0xc8
+
+/* Intel i860 registers */
+#define INTEL_I860_MCHCFG 0x50
+#define INTEL_I860_ERRSTS 0xc8
+
+/* Intel i810 registers */
+#define I810_GMADR_BAR 0
+#define I810_MMADR_BAR 1
+#define I810_PTE_BASE 0x10000
+#define I810_PTE_MAIN_UNCACHED 0x00000000
+#define I810_PTE_LOCAL 0x00000002
+#define I810_PTE_VALID 0x00000001
+#define I830_PTE_SYSTEM_CACHED 0x00000006
+
+#define I810_SMRAM_MISCC 0x70
+#define I810_GFX_MEM_WIN_SIZE 0x00010000
+#define I810_GFX_MEM_WIN_32M 0x00010000
+#define I810_GMS 0x000000c0
+#define I810_GMS_DISABLE 0x00000000
+#define I810_PGETBL_CTL 0x2020
+#define I810_PGETBL_ENABLED 0x00000001
+/* Note: PGETBL_CTL2 has a different offset on G33. */
+#define I965_PGETBL_CTL2 0x20c4
+#define I965_PGETBL_SIZE_MASK 0x0000000e
+#define I965_PGETBL_SIZE_512KB (0 << 1)
+#define I965_PGETBL_SIZE_256KB (1 << 1)
+#define I965_PGETBL_SIZE_128KB (2 << 1)
+#define I965_PGETBL_SIZE_1MB (3 << 1)
+#define I965_PGETBL_SIZE_2MB (4 << 1)
+#define I965_PGETBL_SIZE_1_5MB (5 << 1)
+#define G33_GMCH_SIZE_MASK (3 << 8)
+#define G33_GMCH_SIZE_1M (1 << 8)
+#define G33_GMCH_SIZE_2M (2 << 8)
+#define G4x_GMCH_SIZE_MASK (0xf << 8)
+#define G4x_GMCH_SIZE_1M (0x1 << 8)
+#define G4x_GMCH_SIZE_2M (0x3 << 8)
+#define G4x_GMCH_SIZE_VT_EN (0x8 << 8)
+#define G4x_GMCH_SIZE_VT_1M (G4x_GMCH_SIZE_1M | G4x_GMCH_SIZE_VT_EN)
+#define G4x_GMCH_SIZE_VT_1_5M ((0x2 << 8) | G4x_GMCH_SIZE_VT_EN)
+#define G4x_GMCH_SIZE_VT_2M (G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN)
+
+#define GFX_FLSH_CNTL 0x2170 /* 915+ */
+
+#define I810_DRAM_CTL 0x3000
+#define I810_DRAM_ROW_0 0x00000001
+#define I810_DRAM_ROW_0_SDRAM 0x00000001
+
+/* Intel 815 register */
+#define INTEL_815_APCONT 0x51
+#define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF
+
+/* Intel i820 registers */
+#define INTEL_I820_RDCR 0x51
+#define INTEL_I820_ERRSTS 0xc8
+
+/* Intel i840 registers */
+#define INTEL_I840_MCHCFG 0x50
+#define INTEL_I840_ERRSTS 0xc8
+
+/* Intel i850 registers */
+#define INTEL_I850_MCHCFG 0x50
+#define INTEL_I850_ERRSTS 0xc8
+
+/* intel 915G registers */
+#define I915_GMADR_BAR 2
+#define I915_MMADR_BAR 0
+#define I915_PTE_BAR 3
+#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
+#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
+#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
+#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
+#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
+#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
+#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
+
+#define I915_IFPADDR 0x60
+#define I830_HIC 0x70
+
+/* Intel 965G registers */
+#define I965_MSAC 0x62
+#define I965_IFPADDR 0x70
+
+/* Intel 7505 registers */
+#define INTEL_I7505_APSIZE 0x74
+#define INTEL_I7505_NCAPID 0x60
+#define INTEL_I7505_NISTAT 0x6c
+#define INTEL_I7505_ATTBASE 0x78
+#define INTEL_I7505_ERRSTS 0x42
+#define INTEL_I7505_AGPCTRL 0x70
+#define INTEL_I7505_MCHCFG 0x50
+
+/* pci devices ids */
+#define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588
+#define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a
+#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970
+#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972
+#define PCI_DEVICE_ID_INTEL_82G35_HB 0x2980
+#define PCI_DEVICE_ID_INTEL_82G35_IG 0x2982
+#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990
+#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992
+#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0
+#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
+#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
+#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
+#define PCI_DEVICE_ID_INTEL_82965GME_HB 0x2A10
+#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
+#define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC
+#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
+#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB 0xA010
+#define PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG 0xA011
+#define PCI_DEVICE_ID_INTEL_PINEVIEW_HB 0xA000
+#define PCI_DEVICE_ID_INTEL_PINEVIEW_IG 0xA001
+#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
+#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
+#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0
+#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2
+#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0
+#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
+#define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40
+#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42
+#define PCI_DEVICE_ID_INTEL_B43_1_HB 0x2E90
+#define PCI_DEVICE_ID_INTEL_B43_1_IG 0x2E92
+#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40
+#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42
+#define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00
+#define PCI_DEVICE_ID_INTEL_EAGLELAKE_IG 0x2E02
+#define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10
+#define PCI_DEVICE_ID_INTEL_Q45_IG 0x2E12
+#define PCI_DEVICE_ID_INTEL_G45_HB 0x2E20
+#define PCI_DEVICE_ID_INTEL_G45_IG 0x2E22
+#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
+#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
+
+#endif
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
new file mode 100644
index 00000000000..9a024f899dd
--- /dev/null
+++ b/drivers/char/agp/intel-gtt.c
@@ -0,0 +1,1446 @@
+/*
+ * Intel GTT (Graphics Translation Table) routines
+ *
+ * Caveat: This driver implements the linux agp interface, but this is far from
+ * a agp driver! GTT support ended up here for purely historical reasons: The
+ * old userspace intel graphics drivers needed an interface to map memory into
+ * the GTT. And the drm provides a default interface for graphic devices sitting
+ * on an agp port. So it made sense to fake the GTT support as an agp port to
+ * avoid having to create a new api.
+ *
+ * With gem this does not make much sense anymore, just needlessly complicates
+ * the code. But as long as the old graphics stack is still support, it's stuck
+ * here.
+ *
+ * /fairy-tale-mode off
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/pagemap.h>
+#include <linux/agp_backend.h>
+#include <linux/delay.h>
+#include <asm/smp.h>
+#include "agp.h"
+#include "intel-agp.h"
+#include <drm/intel-gtt.h>
+
+/*
+ * If we have Intel graphics, we're not going to have anything other than
+ * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
+ * on the Intel IOMMU support (CONFIG_INTEL_IOMMU).
+ * Only newer chipsets need to bother with this, of course.
+ */
+#ifdef CONFIG_INTEL_IOMMU
+#define USE_PCI_DMA_API 1
+#else
+#define USE_PCI_DMA_API 0
+#endif
+
+struct intel_gtt_driver {
+ unsigned int gen : 8;
+ unsigned int is_g33 : 1;
+ unsigned int is_pineview : 1;
+ unsigned int is_ironlake : 1;
+ unsigned int has_pgtbl_enable : 1;
+ unsigned int dma_mask_size : 8;
+ /* Chipset specific GTT setup */
+ int (*setup)(void);
+ /* This should undo anything done in ->setup() save the unmapping
+ * of the mmio register file, that's done in the generic code. */
+ void (*cleanup)(void);
+ void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags);
+ /* Flags is a more or less chipset specific opaque value.
+ * For chipsets that need to support old ums (non-gem) code, this
+ * needs to be identical to the various supported agp memory types! */
+ bool (*check_flags)(unsigned int flags);
+ void (*chipset_flush)(void);
+};
+
+static struct _intel_private {
+ const struct intel_gtt_driver *driver;
+ struct pci_dev *pcidev; /* device one */
+ struct pci_dev *bridge_dev;
+ u8 __iomem *registers;
+ phys_addr_t gtt_phys_addr;
+ u32 PGETBL_save;
+ u32 __iomem *gtt; /* I915G */
+ bool clear_fake_agp; /* on first access via agp, fill with scratch */
+ int num_dcache_entries;
+ void __iomem *i9xx_flush_page;
+ char *i81x_gtt_table;
+ struct resource ifp_resource;
+ int resource_valid;
+ struct page *scratch_page;
+ phys_addr_t scratch_page_dma;
+ int refcount;
+ /* Whether i915 needs to use the dmar apis or not. */
+ unsigned int needs_dmar : 1;
+ phys_addr_t gma_bus_addr;
+ /* Size of memory reserved for graphics by the BIOS */
+ unsigned int stolen_size;
+ /* Total number of gtt entries. */
+ unsigned int gtt_total_entries;
+ /* Part of the gtt that is mappable by the cpu, for those chips where
+ * this is not the full gtt. */
+ unsigned int gtt_mappable_entries;
+} intel_private;
+
+#define INTEL_GTT_GEN intel_private.driver->gen
+#define IS_G33 intel_private.driver->is_g33
+#define IS_PINEVIEW intel_private.driver->is_pineview
+#define IS_IRONLAKE intel_private.driver->is_ironlake
+#define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+static int intel_gtt_map_memory(struct page **pages,
+ unsigned int num_entries,
+ struct sg_table *st)
+{
+ struct scatterlist *sg;
+ int i;
+
+ DBG("try mapping %lu pages\n", (unsigned long)num_entries);
+
+ if (sg_alloc_table(st, num_entries, GFP_KERNEL))
+ goto err;
+
+ for_each_sg(st->sgl, sg, num_entries, i)
+ sg_set_page(sg, pages[i], PAGE_SIZE, 0);
+
+ if (!pci_map_sg(intel_private.pcidev,
+ st->sgl, st->nents, PCI_DMA_BIDIRECTIONAL))
+ goto err;
+
+ return 0;
+
+err:
+ sg_free_table(st);
+ return -ENOMEM;
+}
+
+static void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg)
+{
+ struct sg_table st;
+ DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count);
+
+ pci_unmap_sg(intel_private.pcidev, sg_list,
+ num_sg, PCI_DMA_BIDIRECTIONAL);
+
+ st.sgl = sg_list;
+ st.orig_nents = st.nents = num_sg;
+
+ sg_free_table(&st);
+}
+
+static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+{
+ return;
+}
+
+/* Exists to support ARGB cursors */
+static struct page *i8xx_alloc_pages(void)
+{
+ struct page *page;
+
+ page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
+ if (page == NULL)
+ return NULL;
+
+ if (set_pages_uc(page, 4) < 0) {
+ set_pages_wb(page, 4);
+ __free_pages(page, 2);
+ return NULL;
+ }
+ get_page(page);
+ atomic_inc(&agp_bridge->current_memory_agp);
+ return page;
+}
+
+static void i8xx_destroy_pages(struct page *page)
+{
+ if (page == NULL)
+ return;
+
+ set_pages_wb(page, 4);
+ put_page(page);
+ __free_pages(page, 2);
+ atomic_dec(&agp_bridge->current_memory_agp);
+}
+#endif
+
+#define I810_GTT_ORDER 4
+static int i810_setup(void)
+{
+ phys_addr_t reg_addr;
+ char *gtt_table;
+
+ /* i81x does not preallocate the gtt. It's always 64kb in size. */
+ gtt_table = alloc_gatt_pages(I810_GTT_ORDER);
+ if (gtt_table == NULL)
+ return -ENOMEM;
+ intel_private.i81x_gtt_table = gtt_table;
+
+ reg_addr = pci_resource_start(intel_private.pcidev, I810_MMADR_BAR);
+
+ intel_private.registers = ioremap(reg_addr, KB(64));
+ if (!intel_private.registers)
+ return -ENOMEM;
+
+ writel(virt_to_phys(gtt_table) | I810_PGETBL_ENABLED,
+ intel_private.registers+I810_PGETBL_CTL);
+
+ intel_private.gtt_phys_addr = reg_addr + I810_PTE_BASE;
+
+ if ((readl(intel_private.registers+I810_DRAM_CTL)
+ & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
+ dev_info(&intel_private.pcidev->dev,
+ "detected 4MB dedicated video ram\n");
+ intel_private.num_dcache_entries = 1024;
+ }
+
+ return 0;
+}
+
+static void i810_cleanup(void)
+{
+ writel(0, intel_private.registers+I810_PGETBL_CTL);
+ free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER);
+}
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start,
+ int type)
+{
+ int i;
+
+ if ((pg_start + mem->page_count)
+ > intel_private.num_dcache_entries)
+ return -EINVAL;
+
+ if (!mem->is_flushed)
+ global_cache_flush();
+
+ for (i = pg_start; i < (pg_start + mem->page_count); i++) {
+ dma_addr_t addr = i << PAGE_SHIFT;
+ intel_private.driver->write_entry(addr,
+ i, type);
+ }
+ readl(intel_private.gtt+i-1);
+
+ return 0;
+}
+
+/*
+ * The i810/i830 requires a physical address to program its mouse
+ * pointer into hardware.
+ * However the Xserver still writes to it through the agp aperture.
+ */
+static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
+{
+ struct agp_memory *new;
+ struct page *page;
+
+ switch (pg_count) {
+ case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge);
+ break;
+ case 4:
+ /* kludge to get 4 physical pages for ARGB cursor */
+ page = i8xx_alloc_pages();
+ break;
+ default:
+ return NULL;
+ }
+
+ if (page == NULL)
+ return NULL;
+
+ new = agp_create_memory(pg_count);
+ if (new == NULL)
+ return NULL;
+
+ new->pages[0] = page;
+ if (pg_count == 4) {
+ /* kludge to get 4 physical pages for ARGB cursor */
+ new->pages[1] = new->pages[0] + 1;
+ new->pages[2] = new->pages[1] + 1;
+ new->pages[3] = new->pages[2] + 1;
+ }
+ new->page_count = pg_count;
+ new->num_scratch_pages = pg_count;
+ new->type = AGP_PHYS_MEMORY;
+ new->physical = page_to_phys(new->pages[0]);
+ return new;
+}
+
+static void intel_i810_free_by_type(struct agp_memory *curr)
+{
+ agp_free_key(curr->key);
+ if (curr->type == AGP_PHYS_MEMORY) {
+ if (curr->page_count == 4)
+ i8xx_destroy_pages(curr->pages[0]);
+ else {
+ agp_bridge->driver->agp_destroy_page(curr->pages[0],
+ AGP_PAGE_DESTROY_UNMAP);
+ agp_bridge->driver->agp_destroy_page(curr->pages[0],
+ AGP_PAGE_DESTROY_FREE);
+ }
+ agp_free_page_array(curr);
+ }
+ kfree(curr);
+}
+#endif
+
+static int intel_gtt_setup_scratch_page(void)
+{
+ struct page *page;
+ dma_addr_t dma_addr;
+
+ page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
+ if (page == NULL)
+ return -ENOMEM;
+ get_page(page);
+ set_pages_uc(page, 1);
+
+ if (intel_private.needs_dmar) {
+ dma_addr = pci_map_page(intel_private.pcidev, page, 0,
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ if (pci_dma_mapping_error(intel_private.pcidev, dma_addr))
+ return -EINVAL;
+
+ intel_private.scratch_page_dma = dma_addr;
+ } else
+ intel_private.scratch_page_dma = page_to_phys(page);
+
+ intel_private.scratch_page = page;
+
+ return 0;
+}
+
+static void i810_write_entry(dma_addr_t addr, unsigned int entry,
+ unsigned int flags)
+{
+ u32 pte_flags = I810_PTE_VALID;
+
+ switch (flags) {
+ case AGP_DCACHE_MEMORY:
+ pte_flags |= I810_PTE_LOCAL;
+ break;
+ case AGP_USER_CACHED_MEMORY:
+ pte_flags |= I830_PTE_SYSTEM_CACHED;
+ break;
+ }
+
+ writel(addr | pte_flags, intel_private.gtt + entry);
+}
+
+static const struct aper_size_info_fixed intel_fake_agp_sizes[] = {
+ {32, 8192, 3},
+ {64, 16384, 4},
+ {128, 32768, 5},
+ {256, 65536, 6},
+ {512, 131072, 7},
+};
+
+static unsigned int intel_gtt_stolen_size(void)
+{
+ u16 gmch_ctrl;
+ u8 rdct;
+ int local = 0;
+ static const int ddt[4] = { 0, 16, 32, 64 };
+ unsigned int stolen_size = 0;
+
+ if (INTEL_GTT_GEN == 1)
+ return 0; /* no stolen mem on i81x */
+
+ pci_read_config_word(intel_private.bridge_dev,
+ I830_GMCH_CTRL, &gmch_ctrl);
+
+ if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
+ intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I830_GMCH_GMS_STOLEN_512:
+ stolen_size = KB(512);
+ break;
+ case I830_GMCH_GMS_STOLEN_1024:
+ stolen_size = MB(1);
+ break;
+ case I830_GMCH_GMS_STOLEN_8192:
+ stolen_size = MB(8);
+ break;
+ case I830_GMCH_GMS_LOCAL:
+ rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
+ stolen_size = (I830_RDRAM_ND(rdct) + 1) *
+ MB(ddt[I830_RDRAM_DDT(rdct)]);
+ local = 1;
+ break;
+ default:
+ stolen_size = 0;
+ break;
+ }
+ } else {
+ switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
+ case I855_GMCH_GMS_STOLEN_1M:
+ stolen_size = MB(1);
+ break;
+ case I855_GMCH_GMS_STOLEN_4M:
+ stolen_size = MB(4);
+ break;
+ case I855_GMCH_GMS_STOLEN_8M:
+ stolen_size = MB(8);
+ break;
+ case I855_GMCH_GMS_STOLEN_16M:
+ stolen_size = MB(16);
+ break;
+ case I855_GMCH_GMS_STOLEN_32M:
+ stolen_size = MB(32);
+ break;
+ case I915_GMCH_GMS_STOLEN_48M:
+ stolen_size = MB(48);
+ break;
+ case I915_GMCH_GMS_STOLEN_64M:
+ stolen_size = MB(64);
+ break;
+ case G33_GMCH_GMS_STOLEN_128M:
+ stolen_size = MB(128);
+ break;
+ case G33_GMCH_GMS_STOLEN_256M:
+ stolen_size = MB(256);
+ break;
+ case INTEL_GMCH_GMS_STOLEN_96M:
+ stolen_size = MB(96);
+ break;
+ case INTEL_GMCH_GMS_STOLEN_160M:
+ stolen_size = MB(160);
+ break;
+ case INTEL_GMCH_GMS_STOLEN_224M:
+ stolen_size = MB(224);
+ break;
+ case INTEL_GMCH_GMS_STOLEN_352M:
+ stolen_size = MB(352);
+ break;
+ default:
+ stolen_size = 0;
+ break;
+ }
+ }
+
+ if (stolen_size > 0) {
+ dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n",
+ stolen_size / KB(1), local ? "local" : "stolen");
+ } else {
+ dev_info(&intel_private.bridge_dev->dev,
+ "no pre-allocated video memory detected\n");
+ stolen_size = 0;
+ }
+
+ return stolen_size;
+}
+
+static void i965_adjust_pgetbl_size(unsigned int size_flag)
+{
+ u32 pgetbl_ctl, pgetbl_ctl2;
+
+ /* ensure that ppgtt is disabled */
+ pgetbl_ctl2 = readl(intel_private.registers+I965_PGETBL_CTL2);
+ pgetbl_ctl2 &= ~I810_PGETBL_ENABLED;
+ writel(pgetbl_ctl2, intel_private.registers+I965_PGETBL_CTL2);
+
+ /* write the new ggtt size */
+ pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+ pgetbl_ctl &= ~I965_PGETBL_SIZE_MASK;
+ pgetbl_ctl |= size_flag;
+ writel(pgetbl_ctl, intel_private.registers+I810_PGETBL_CTL);
+}
+
+static unsigned int i965_gtt_total_entries(void)
+{
+ int size;
+ u32 pgetbl_ctl;
+ u16 gmch_ctl;
+
+ pci_read_config_word(intel_private.bridge_dev,
+ I830_GMCH_CTRL, &gmch_ctl);
+
+ if (INTEL_GTT_GEN == 5) {
+ switch (gmch_ctl & G4x_GMCH_SIZE_MASK) {
+ case G4x_GMCH_SIZE_1M:
+ case G4x_GMCH_SIZE_VT_1M:
+ i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1MB);
+ break;
+ case G4x_GMCH_SIZE_VT_1_5M:
+ i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1_5MB);
+ break;
+ case G4x_GMCH_SIZE_2M:
+ case G4x_GMCH_SIZE_VT_2M:
+ i965_adjust_pgetbl_size(I965_PGETBL_SIZE_2MB);
+ break;
+ }
+ }
+
+ pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
+
+ switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
+ case I965_PGETBL_SIZE_128KB:
+ size = KB(128);
+ break;
+ case I965_PGETBL_SIZE_256KB:
+ size = KB(256);
+ break;
+ case I965_PGETBL_SIZE_512KB:
+ size = KB(512);
+ break;
+ /* GTT pagetable sizes bigger than 512KB are not possible on G33! */
+ case I965_PGETBL_SIZE_1MB:
+ size = KB(1024);
+ break;
+ case I965_PGETBL_SIZE_2MB:
+ size = KB(2048);
+ break;
+ case I965_PGETBL_SIZE_1_5MB:
+ size = KB(1024 + 512);
+ break;
+ default:
+ dev_info(&intel_private.pcidev->dev,
+ "unknown page table size, assuming 512KB\n");
+ size = KB(512);
+ }
+
+ return size/4;
+}
+
+static unsigned int intel_gtt_total_entries(void)
+{
+ if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5)
+ return i965_gtt_total_entries();
+ else {
+ /* On previous hardware, the GTT size was just what was
+ * required to map the aperture.
+ */
+ return intel_private.gtt_mappable_entries;
+ }
+}
+
+static unsigned int intel_gtt_mappable_entries(void)
+{
+ unsigned int aperture_size;
+
+ if (INTEL_GTT_GEN == 1) {
+ u32 smram_miscc;
+
+ pci_read_config_dword(intel_private.bridge_dev,
+ I810_SMRAM_MISCC, &smram_miscc);
+
+ if ((smram_miscc & I810_GFX_MEM_WIN_SIZE)
+ == I810_GFX_MEM_WIN_32M)
+ aperture_size = MB(32);
+ else
+ aperture_size = MB(64);
+ } else if (INTEL_GTT_GEN == 2) {
+ u16 gmch_ctrl;
+
+ pci_read_config_word(intel_private.bridge_dev,
+ I830_GMCH_CTRL, &gmch_ctrl);
+
+ if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_64M)
+ aperture_size = MB(64);
+ else
+ aperture_size = MB(128);
+ } else {
+ /* 9xx supports large sizes, just look at the length */
+ aperture_size = pci_resource_len(intel_private.pcidev, 2);
+ }
+
+ return aperture_size >> PAGE_SHIFT;
+}
+
+static void intel_gtt_teardown_scratch_page(void)
+{
+ set_pages_wb(intel_private.scratch_page, 1);
+ pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma,
+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+ put_page(intel_private.scratch_page);
+ __free_page(intel_private.scratch_page);
+}
+
+static void intel_gtt_cleanup(void)
+{
+ intel_private.driver->cleanup();
+
+ iounmap(intel_private.gtt);
+ iounmap(intel_private.registers);
+
+ intel_gtt_teardown_scratch_page();
+}
+
+/* Certain Gen5 chipsets require require idling the GPU before
+ * unmapping anything from the GTT when VT-d is enabled.
+ */
+static inline int needs_ilk_vtd_wa(void)
+{
+#ifdef CONFIG_INTEL_IOMMU
+ const unsigned short gpu_devid = intel_private.pcidev->device;
+
+ /* Query intel_iommu to see if we need the workaround. Presumably that
+ * was loaded first.
+ */
+ if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB ||
+ gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
+ intel_iommu_gfx_mapped)
+ return 1;
+#endif
+ return 0;
+}
+
+static bool intel_gtt_can_wc(void)
+{
+ if (INTEL_GTT_GEN <= 2)
+ return false;
+
+ if (INTEL_GTT_GEN >= 6)
+ return false;
+
+ /* Reports of major corruption with ILK vt'd enabled */
+ if (needs_ilk_vtd_wa())
+ return false;
+
+ return true;
+}
+
+static int intel_gtt_init(void)
+{
+ u32 gtt_map_size;
+ int ret, bar;
+
+ ret = intel_private.driver->setup();
+ if (ret != 0)
+ return ret;
+
+ intel_private.gtt_mappable_entries = intel_gtt_mappable_entries();
+ intel_private.gtt_total_entries = intel_gtt_total_entries();
+
+ /* save the PGETBL reg for resume */
+ intel_private.PGETBL_save =
+ readl(intel_private.registers+I810_PGETBL_CTL)
+ & ~I810_PGETBL_ENABLED;
+ /* we only ever restore the register when enabling the PGTBL... */
+ if (HAS_PGTBL_EN)
+ intel_private.PGETBL_save |= I810_PGETBL_ENABLED;
+
+ dev_info(&intel_private.bridge_dev->dev,
+ "detected gtt size: %dK total, %dK mappable\n",
+ intel_private.gtt_total_entries * 4,
+ intel_private.gtt_mappable_entries * 4);
+
+ gtt_map_size = intel_private.gtt_total_entries * 4;
+
+ intel_private.gtt = NULL;
+ if (intel_gtt_can_wc())
+ intel_private.gtt = ioremap_wc(intel_private.gtt_phys_addr,
+ gtt_map_size);
+ if (intel_private.gtt == NULL)
+ intel_private.gtt = ioremap(intel_private.gtt_phys_addr,
+ gtt_map_size);
+ if (intel_private.gtt == NULL) {
+ intel_private.driver->cleanup();
+ iounmap(intel_private.registers);
+ return -ENOMEM;
+ }
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+ global_cache_flush(); /* FIXME: ? */
+#endif
+
+ intel_private.stolen_size = intel_gtt_stolen_size();
+
+ intel_private.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2;
+
+ ret = intel_gtt_setup_scratch_page();
+ if (ret != 0) {
+ intel_gtt_cleanup();
+ return ret;
+ }
+
+ if (INTEL_GTT_GEN <= 2)
+ bar = I810_GMADR_BAR;
+ else
+ bar = I915_GMADR_BAR;
+
+ intel_private.gma_bus_addr = pci_bus_address(intel_private.pcidev, bar);
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+static int intel_fake_agp_fetch_size(void)
+{
+ int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes);
+ unsigned int aper_size;
+ int i;
+
+ aper_size = (intel_private.gtt_mappable_entries << PAGE_SHIFT) / MB(1);
+
+ for (i = 0; i < num_sizes; i++) {
+ if (aper_size == intel_fake_agp_sizes[i].size) {
+ agp_bridge->current_size =
+ (void *) (intel_fake_agp_sizes + i);
+ return aper_size;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static void i830_cleanup(void)
+{
+}
+
+/* The chipset_flush interface needs to get data that has already been
+ * flushed out of the CPU all the way out to main memory, because the GPU
+ * doesn't snoop those buffers.
+ *
+ * The 8xx series doesn't have the same lovely interface for flushing the
+ * chipset write buffers that the later chips do. According to the 865
+ * specs, it's 64 octwords, or 1KB. So, to get those previous things in
+ * that buffer out, we just fill 1KB and clflush it out, on the assumption
+ * that it'll push whatever was in there out. It appears to work.
+ */
+static void i830_chipset_flush(void)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+ /* Forcibly evict everything from the CPU write buffers.
+ * clflush appears to be insufficient.
+ */
+ wbinvd_on_all_cpus();
+
+ /* Now we've only seen documents for this magic bit on 855GM,
+ * we hope it exists for the other gen2 chipsets...
+ *
+ * Also works as advertised on my 845G.
+ */
+ writel(readl(intel_private.registers+I830_HIC) | (1<<31),
+ intel_private.registers+I830_HIC);
+
+ while (readl(intel_private.registers+I830_HIC) & (1<<31)) {
+ if (time_after(jiffies, timeout))
+ break;
+
+ udelay(50);
+ }
+}
+
+static void i830_write_entry(dma_addr_t addr, unsigned int entry,
+ unsigned int flags)
+{
+ u32 pte_flags = I810_PTE_VALID;
+
+ if (flags == AGP_USER_CACHED_MEMORY)
+ pte_flags |= I830_PTE_SYSTEM_CACHED;
+
+ writel(addr | pte_flags, intel_private.gtt + entry);
+}
+
+bool intel_enable_gtt(void)
+{
+ u8 __iomem *reg;
+
+ if (INTEL_GTT_GEN == 2) {
+ u16 gmch_ctrl;
+
+ pci_read_config_word(intel_private.bridge_dev,
+ I830_GMCH_CTRL, &gmch_ctrl);
+ gmch_ctrl |= I830_GMCH_ENABLED;
+ pci_write_config_word(intel_private.bridge_dev,
+ I830_GMCH_CTRL, gmch_ctrl);
+
+ pci_read_config_word(intel_private.bridge_dev,
+ I830_GMCH_CTRL, &gmch_ctrl);
+ if ((gmch_ctrl & I830_GMCH_ENABLED) == 0) {
+ dev_err(&intel_private.pcidev->dev,
+ "failed to enable the GTT: GMCH_CTRL=%x\n",
+ gmch_ctrl);
+ return false;
+ }
+ }
+
+ /* On the resume path we may be adjusting the PGTBL value, so
+ * be paranoid and flush all chipset write buffers...
+ */
+ if (INTEL_GTT_GEN >= 3)
+ writel(0, intel_private.registers+GFX_FLSH_CNTL);
+
+ reg = intel_private.registers+I810_PGETBL_CTL;
+ writel(intel_private.PGETBL_save, reg);
+ if (HAS_PGTBL_EN && (readl(reg) & I810_PGETBL_ENABLED) == 0) {
+ dev_err(&intel_private.pcidev->dev,
+ "failed to enable the GTT: PGETBL=%x [expected %x]\n",
+ readl(reg), intel_private.PGETBL_save);
+ return false;
+ }
+
+ if (INTEL_GTT_GEN >= 3)
+ writel(0, intel_private.registers+GFX_FLSH_CNTL);
+
+ return true;
+}
+EXPORT_SYMBOL(intel_enable_gtt);
+
+static int i830_setup(void)
+{
+ phys_addr_t reg_addr;
+
+ reg_addr = pci_resource_start(intel_private.pcidev, I810_MMADR_BAR);
+
+ intel_private.registers = ioremap(reg_addr, KB(64));
+ if (!intel_private.registers)
+ return -ENOMEM;
+
+ intel_private.gtt_phys_addr = reg_addr + I810_PTE_BASE;
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+static int intel_fake_agp_create_gatt_table(struct agp_bridge_data *bridge)
+{
+ agp_bridge->gatt_table_real = NULL;
+ agp_bridge->gatt_table = NULL;
+ agp_bridge->gatt_bus_addr = 0;
+
+ return 0;
+}
+
+static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge)
+{
+ return 0;
+}
+
+static int intel_fake_agp_configure(void)
+{
+ if (!intel_enable_gtt())
+ return -EIO;
+
+ intel_private.clear_fake_agp = true;
+ agp_bridge->gart_bus_addr = intel_private.gma_bus_addr;
+
+ return 0;
+}
+#endif
+
+static bool i830_check_flags(unsigned int flags)
+{
+ switch (flags) {
+ case 0:
+ case AGP_PHYS_MEMORY:
+ case AGP_USER_CACHED_MEMORY:
+ case AGP_USER_MEMORY:
+ return true;
+ }
+
+ return false;
+}
+
+void intel_gtt_insert_sg_entries(struct sg_table *st,
+ unsigned int pg_start,
+ unsigned int flags)
+{
+ struct scatterlist *sg;
+ unsigned int len, m;
+ int i, j;
+
+ j = pg_start;
+
+ /* sg may merge pages, but we have to separate
+ * per-page addr for GTT */
+ for_each_sg(st->sgl, sg, st->nents, i) {
+ len = sg_dma_len(sg) >> PAGE_SHIFT;
+ for (m = 0; m < len; m++) {
+ dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
+ intel_private.driver->write_entry(addr, j, flags);
+ j++;
+ }
+ }
+ readl(intel_private.gtt+j-1);
+}
+EXPORT_SYMBOL(intel_gtt_insert_sg_entries);
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+static void intel_gtt_insert_pages(unsigned int first_entry,
+ unsigned int num_entries,
+ struct page **pages,
+ unsigned int flags)
+{
+ int i, j;
+
+ for (i = 0, j = first_entry; i < num_entries; i++, j++) {
+ dma_addr_t addr = page_to_phys(pages[i]);
+ intel_private.driver->write_entry(addr,
+ j, flags);
+ }
+ readl(intel_private.gtt+j-1);
+}
+
+static int intel_fake_agp_insert_entries(struct agp_memory *mem,
+ off_t pg_start, int type)
+{
+ int ret = -EINVAL;
+
+ if (intel_private.clear_fake_agp) {
+ int start = intel_private.stolen_size / PAGE_SIZE;
+ int end = intel_private.gtt_mappable_entries;
+ intel_gtt_clear_range(start, end - start);
+ intel_private.clear_fake_agp = false;
+ }
+
+ if (INTEL_GTT_GEN == 1 && type == AGP_DCACHE_MEMORY)
+ return i810_insert_dcache_entries(mem, pg_start, type);
+
+ if (mem->page_count == 0)
+ goto out;
+
+ if (pg_start + mem->page_count > intel_private.gtt_total_entries)
+ goto out_err;
+
+ if (type != mem->type)
+ goto out_err;
+
+ if (!intel_private.driver->check_flags(type))
+ goto out_err;
+
+ if (!mem->is_flushed)
+ global_cache_flush();
+
+ if (intel_private.needs_dmar) {
+ struct sg_table st;
+
+ ret = intel_gtt_map_memory(mem->pages, mem->page_count, &st);
+ if (ret != 0)
+ return ret;
+
+ intel_gtt_insert_sg_entries(&st, pg_start, type);
+ mem->sg_list = st.sgl;
+ mem->num_sg = st.nents;
+ } else
+ intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages,
+ type);
+
+out:
+ ret = 0;
+out_err:
+ mem->is_flushed = true;
+ return ret;
+}
+#endif
+
+void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries)
+{
+ unsigned int i;
+
+ for (i = first_entry; i < (first_entry + num_entries); i++) {
+ intel_private.driver->write_entry(intel_private.scratch_page_dma,
+ i, 0);
+ }
+ readl(intel_private.gtt+i-1);
+}
+EXPORT_SYMBOL(intel_gtt_clear_range);
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+static int intel_fake_agp_remove_entries(struct agp_memory *mem,
+ off_t pg_start, int type)
+{
+ if (mem->page_count == 0)
+ return 0;
+
+ intel_gtt_clear_range(pg_start, mem->page_count);
+
+ if (intel_private.needs_dmar) {
+ intel_gtt_unmap_memory(mem->sg_list, mem->num_sg);
+ mem->sg_list = NULL;
+ mem->num_sg = 0;
+ }
+
+ return 0;
+}
+
+static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count,
+ int type)
+{
+ struct agp_memory *new;
+
+ if (type == AGP_DCACHE_MEMORY && INTEL_GTT_GEN == 1) {
+ if (pg_count != intel_private.num_dcache_entries)
+ return NULL;
+
+ new = agp_create_memory(1);
+ if (new == NULL)
+ return NULL;
+
+ new->type = AGP_DCACHE_MEMORY;
+ new->page_count = pg_count;
+ new->num_scratch_pages = 0;
+ agp_free_page_array(new);
+ return new;
+ }
+ if (type == AGP_PHYS_MEMORY)
+ return alloc_agpphysmem_i8xx(pg_count, type);
+ /* always return NULL for other allocation types for now */
+ return NULL;
+}
+#endif
+
+static int intel_alloc_chipset_flush_resource(void)
+{
+ int ret;
+ ret = pci_bus_alloc_resource(intel_private.bridge_dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
+ PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
+ pcibios_align_resource, intel_private.bridge_dev);
+
+ return ret;
+}
+
+static void intel_i915_setup_chipset_flush(void)
+{
+ int ret;
+ u32 temp;
+
+ pci_read_config_dword(intel_private.bridge_dev, I915_IFPADDR, &temp);
+ if (!(temp & 0x1)) {
+ intel_alloc_chipset_flush_resource();
+ intel_private.resource_valid = 1;
+ pci_write_config_dword(intel_private.bridge_dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
+ } else {
+ temp &= ~1;
+
+ intel_private.resource_valid = 1;
+ intel_private.ifp_resource.start = temp;
+ intel_private.ifp_resource.end = temp + PAGE_SIZE;
+ ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
+ /* some BIOSes reserve this area in a pnp some don't */
+ if (ret)
+ intel_private.resource_valid = 0;
+ }
+}
+
+static void intel_i965_g33_setup_chipset_flush(void)
+{
+ u32 temp_hi, temp_lo;
+ int ret;
+
+ pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4, &temp_hi);
+ pci_read_config_dword(intel_private.bridge_dev, I965_IFPADDR, &temp_lo);
+
+ if (!(temp_lo & 0x1)) {
+
+ intel_alloc_chipset_flush_resource();
+
+ intel_private.resource_valid = 1;
+ pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR + 4,
+ upper_32_bits(intel_private.ifp_resource.start));
+ pci_write_config_dword(intel_private.bridge_dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
+ } else {
+ u64 l64;
+
+ temp_lo &= ~0x1;
+ l64 = ((u64)temp_hi << 32) | temp_lo;
+
+ intel_private.resource_valid = 1;
+ intel_private.ifp_resource.start = l64;
+ intel_private.ifp_resource.end = l64 + PAGE_SIZE;
+ ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
+ /* some BIOSes reserve this area in a pnp some don't */
+ if (ret)
+ intel_private.resource_valid = 0;
+ }
+}
+
+static void intel_i9xx_setup_flush(void)
+{
+ /* return if already configured */
+ if (intel_private.ifp_resource.start)
+ return;
+
+ if (INTEL_GTT_GEN == 6)
+ return;
+
+ /* setup a resource for this object */
+ intel_private.ifp_resource.name = "Intel Flush Page";
+ intel_private.ifp_resource.flags = IORESOURCE_MEM;
+
+ /* Setup chipset flush for 915 */
+ if (IS_G33 || INTEL_GTT_GEN >= 4) {
+ intel_i965_g33_setup_chipset_flush();
+ } else {
+ intel_i915_setup_chipset_flush();
+ }
+
+ if (intel_private.ifp_resource.start)
+ intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
+ if (!intel_private.i9xx_flush_page)
+ dev_err(&intel_private.pcidev->dev,
+ "can't ioremap flush page - no chipset flushing\n");
+}
+
+static void i9xx_cleanup(void)
+{
+ if (intel_private.i9xx_flush_page)
+ iounmap(intel_private.i9xx_flush_page);
+ if (intel_private.resource_valid)
+ release_resource(&intel_private.ifp_resource);
+ intel_private.ifp_resource.start = 0;
+ intel_private.resource_valid = 0;
+}
+
+static void i9xx_chipset_flush(void)
+{
+ if (intel_private.i9xx_flush_page)
+ writel(1, intel_private.i9xx_flush_page);
+}
+
+static void i965_write_entry(dma_addr_t addr,
+ unsigned int entry,
+ unsigned int flags)
+{
+ u32 pte_flags;
+
+ pte_flags = I810_PTE_VALID;
+ if (flags == AGP_USER_CACHED_MEMORY)
+ pte_flags |= I830_PTE_SYSTEM_CACHED;
+
+ /* Shift high bits down */
+ addr |= (addr >> 28) & 0xf0;
+ writel(addr | pte_flags, intel_private.gtt + entry);
+}
+
+static int i9xx_setup(void)
+{
+ phys_addr_t reg_addr;
+ int size = KB(512);
+
+ reg_addr = pci_resource_start(intel_private.pcidev, I915_MMADR_BAR);
+
+ intel_private.registers = ioremap(reg_addr, size);
+ if (!intel_private.registers)
+ return -ENOMEM;
+
+ switch (INTEL_GTT_GEN) {
+ case 3:
+ intel_private.gtt_phys_addr =
+ pci_resource_start(intel_private.pcidev, I915_PTE_BAR);
+ break;
+ case 5:
+ intel_private.gtt_phys_addr = reg_addr + MB(2);
+ break;
+ default:
+ intel_private.gtt_phys_addr = reg_addr + KB(512);
+ break;
+ }
+
+ intel_i9xx_setup_flush();
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+static const struct agp_bridge_driver intel_fake_agp_driver = {
+ .owner = THIS_MODULE,
+ .size_type = FIXED_APER_SIZE,
+ .aperture_sizes = intel_fake_agp_sizes,
+ .num_aperture_sizes = ARRAY_SIZE(intel_fake_agp_sizes),
+ .configure = intel_fake_agp_configure,
+ .fetch_size = intel_fake_agp_fetch_size,
+ .cleanup = intel_gtt_cleanup,
+ .agp_enable = intel_fake_agp_enable,
+ .cache_flush = global_cache_flush,
+ .create_gatt_table = intel_fake_agp_create_gatt_table,
+ .free_gatt_table = intel_fake_agp_free_gatt_table,
+ .insert_memory = intel_fake_agp_insert_entries,
+ .remove_memory = intel_fake_agp_remove_entries,
+ .alloc_by_type = intel_fake_agp_alloc_by_type,
+ .free_by_type = intel_i810_free_by_type,
+ .agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
+ .agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+};
+#endif
+
+static const struct intel_gtt_driver i81x_gtt_driver = {
+ .gen = 1,
+ .has_pgtbl_enable = 1,
+ .dma_mask_size = 32,
+ .setup = i810_setup,
+ .cleanup = i810_cleanup,
+ .check_flags = i830_check_flags,
+ .write_entry = i810_write_entry,
+};
+static const struct intel_gtt_driver i8xx_gtt_driver = {
+ .gen = 2,
+ .has_pgtbl_enable = 1,
+ .setup = i830_setup,
+ .cleanup = i830_cleanup,
+ .write_entry = i830_write_entry,
+ .dma_mask_size = 32,
+ .check_flags = i830_check_flags,
+ .chipset_flush = i830_chipset_flush,
+};
+static const struct intel_gtt_driver i915_gtt_driver = {
+ .gen = 3,
+ .has_pgtbl_enable = 1,
+ .setup = i9xx_setup,
+ .cleanup = i9xx_cleanup,
+ /* i945 is the last gpu to need phys mem (for overlay and cursors). */
+ .write_entry = i830_write_entry,
+ .dma_mask_size = 32,
+ .check_flags = i830_check_flags,
+ .chipset_flush = i9xx_chipset_flush,
+};
+static const struct intel_gtt_driver g33_gtt_driver = {
+ .gen = 3,
+ .is_g33 = 1,
+ .setup = i9xx_setup,
+ .cleanup = i9xx_cleanup,
+ .write_entry = i965_write_entry,
+ .dma_mask_size = 36,
+ .check_flags = i830_check_flags,
+ .chipset_flush = i9xx_chipset_flush,
+};
+static const struct intel_gtt_driver pineview_gtt_driver = {
+ .gen = 3,
+ .is_pineview = 1, .is_g33 = 1,
+ .setup = i9xx_setup,
+ .cleanup = i9xx_cleanup,
+ .write_entry = i965_write_entry,
+ .dma_mask_size = 36,
+ .check_flags = i830_check_flags,
+ .chipset_flush = i9xx_chipset_flush,
+};
+static const struct intel_gtt_driver i965_gtt_driver = {
+ .gen = 4,
+ .has_pgtbl_enable = 1,
+ .setup = i9xx_setup,
+ .cleanup = i9xx_cleanup,
+ .write_entry = i965_write_entry,
+ .dma_mask_size = 36,
+ .check_flags = i830_check_flags,
+ .chipset_flush = i9xx_chipset_flush,
+};
+static const struct intel_gtt_driver g4x_gtt_driver = {
+ .gen = 5,
+ .setup = i9xx_setup,
+ .cleanup = i9xx_cleanup,
+ .write_entry = i965_write_entry,
+ .dma_mask_size = 36,
+ .check_flags = i830_check_flags,
+ .chipset_flush = i9xx_chipset_flush,
+};
+static const struct intel_gtt_driver ironlake_gtt_driver = {
+ .gen = 5,
+ .is_ironlake = 1,
+ .setup = i9xx_setup,
+ .cleanup = i9xx_cleanup,
+ .write_entry = i965_write_entry,
+ .dma_mask_size = 36,
+ .check_flags = i830_check_flags,
+ .chipset_flush = i9xx_chipset_flush,
+};
+
+/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
+ * driver and gmch_driver must be non-null, and find_gmch will determine
+ * which one should be used if a gmch_chip_id is present.
+ */
+static const struct intel_gtt_driver_description {
+ unsigned int gmch_chip_id;
+ char *name;
+ const struct intel_gtt_driver *gtt_driver;
+} intel_gtt_chipsets[] = {
+ { PCI_DEVICE_ID_INTEL_82810_IG1, "i810",
+ &i81x_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82810_IG3, "i810",
+ &i81x_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82810E_IG, "i810",
+ &i81x_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82815_CGC, "i815",
+ &i81x_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82830_CGC, "830M",
+ &i8xx_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82845G_IG, "845G",
+ &i8xx_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82854_IG, "854",
+ &i8xx_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM",
+ &i8xx_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_82865_IG, "865",
+ &i8xx_gtt_driver},
+ { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)",
+ &i915_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82915G_IG, "915G",
+ &i915_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM",
+ &i915_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82945G_IG, "945G",
+ &i915_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM",
+ &i915_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME",
+ &i915_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ",
+ &i965_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82G35_IG, "G35",
+ &i965_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q",
+ &i965_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82965G_IG, "965G",
+ &i965_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM",
+ &i965_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE",
+ &i965_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_G33_IG, "G33",
+ &g33_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35",
+ &g33_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33",
+ &g33_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150",
+ &pineview_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150",
+ &pineview_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45",
+ &g4x_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake",
+ &g4x_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43",
+ &g4x_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43",
+ &g4x_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_B43_IG, "B43",
+ &g4x_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_B43_1_IG, "B43",
+ &g4x_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_G41_IG, "G41",
+ &g4x_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
+ "HD Graphics", &ironlake_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
+ "HD Graphics", &ironlake_gtt_driver },
+ { 0, NULL, NULL }
+};
+
+static int find_gmch(u16 device)
+{
+ struct pci_dev *gmch_device;
+
+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
+ if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
+ device, gmch_device);
+ }
+
+ if (!gmch_device)
+ return 0;
+
+ intel_private.pcidev = gmch_device;
+ return 1;
+}
+
+int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
+ struct agp_bridge_data *bridge)
+{
+ int i, mask;
+
+ /*
+ * Can be called from the fake agp driver but also directly from
+ * drm/i915.ko. Hence we need to check whether everything is set up
+ * already.
+ */
+ if (intel_private.driver) {
+ intel_private.refcount++;
+ return 1;
+ }
+
+ for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) {
+ if (gpu_pdev) {
+ if (gpu_pdev->device ==
+ intel_gtt_chipsets[i].gmch_chip_id) {
+ intel_private.pcidev = pci_dev_get(gpu_pdev);
+ intel_private.driver =
+ intel_gtt_chipsets[i].gtt_driver;
+
+ break;
+ }
+ } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
+ intel_private.driver =
+ intel_gtt_chipsets[i].gtt_driver;
+ break;
+ }
+ }
+
+ if (!intel_private.driver)
+ return 0;
+
+ intel_private.refcount++;
+
+#if IS_ENABLED(CONFIG_AGP_INTEL)
+ if (bridge) {
+ bridge->driver = &intel_fake_agp_driver;
+ bridge->dev_private_data = &intel_private;
+ bridge->dev = bridge_pdev;
+ }
+#endif
+
+ intel_private.bridge_dev = pci_dev_get(bridge_pdev);
+
+ dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name);
+
+ mask = intel_private.driver->dma_mask_size;
+ if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
+ dev_err(&intel_private.pcidev->dev,
+ "set gfx device dma mask %d-bit failed!\n", mask);
+ else
+ pci_set_consistent_dma_mask(intel_private.pcidev,
+ DMA_BIT_MASK(mask));
+
+ if (intel_gtt_init() != 0) {
+ intel_gmch_remove();
+
+ return 0;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL(intel_gmch_probe);
+
+void intel_gtt_get(size_t *gtt_total, size_t *stolen_size,
+ phys_addr_t *mappable_base, unsigned long *mappable_end)
+{
+ *gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT;
+ *stolen_size = intel_private.stolen_size;
+ *mappable_base = intel_private.gma_bus_addr;
+ *mappable_end = intel_private.gtt_mappable_entries << PAGE_SHIFT;
+}
+EXPORT_SYMBOL(intel_gtt_get);
+
+void intel_gtt_chipset_flush(void)
+{
+ if (intel_private.driver->chipset_flush)
+ intel_private.driver->chipset_flush();
+}
+EXPORT_SYMBOL(intel_gtt_chipset_flush);
+
+void intel_gmch_remove(void)
+{
+ if (--intel_private.refcount)
+ return;
+
+ if (intel_private.pcidev)
+ pci_dev_put(intel_private.pcidev);
+ if (intel_private.bridge_dev)
+ pci_dev_put(intel_private.bridge_dev);
+ intel_private.driver = NULL;
+}
+EXPORT_SYMBOL(intel_gmch_remove);
+
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c
index 7c14a096b85..c73385cc4b8 100644
--- a/drivers/char/agp/isoch.c
+++ b/drivers/char/agp/isoch.c
@@ -26,7 +26,7 @@ static void agp_3_5_dev_list_insert(struct list_head *head, struct list_head *ne
list_for_each(pos, head) {
cur = list_entry(pos, struct agp_3_5_dev, list);
- if(cur->maxbw > n->maxbw)
+ if (cur->maxbw > n->maxbw)
break;
}
list_add_tail(new, pos);
@@ -54,9 +54,9 @@ static void agp_3_5_dev_list_sort(struct agp_3_5_dev *list, unsigned int ndevs)
}
}
-/*
- * Initialize all isochronous transfer parameters for an AGP 3.0
- * node (i.e. a host bridge in combination with the adapters
+/*
+ * Initialize all isochronous transfer parameters for an AGP 3.0
+ * node (i.e. a host bridge in combination with the adapters
* lying behind it...)
*/
@@ -153,7 +153,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
/* Check if this configuration has any chance of working */
if (tot_bw > target.maxbw) {
- printk(KERN_ERR PFX "isochronous bandwidth required "
+ dev_err(&td->dev, "isochronous bandwidth required "
"by AGP 3.0 devices exceeds that which is supported by "
"the AGP 3.0 bridge!\n");
ret = -ENODEV;
@@ -188,7 +188,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
/* Exit if the minimal ISOCH_N allocation among the masters is more
* than the target can handle. */
if (tot_n > target.n) {
- printk(KERN_ERR PFX "number of isochronous "
+ dev_err(&td->dev, "number of isochronous "
"transactions per period required by AGP 3.0 devices "
"exceeds that which is supported by the AGP 3.0 "
"bridge!\n");
@@ -200,7 +200,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
* this to the hungriest device (as per the spec) */
rem = target.n - tot_n;
- /*
+ /*
* Calculate the minimum isochronous RQ depth needed by each master.
* Along the way, distribute the extra ISOCH_N capability calculated
* above.
@@ -214,7 +214,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
* many writes on the AGP bus).
*/
master[cdev].rq = master[cdev].n;
- if(master[cdev].y > 0x1)
+ if (master[cdev].y > 0x1)
master[cdev].rq *= (1 << (master[cdev].y - 1));
tot_rq += master[cdev].rq;
@@ -229,7 +229,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
/* Exit if the minimal RQ needs of the masters exceeds what the target
* can provide. */
if (tot_rq > rq_isoch) {
- printk(KERN_ERR PFX "number of request queue slots "
+ dev_err(&td->dev, "number of request queue slots "
"required by the isochronous bandwidth requested by "
"AGP 3.0 devices exceeds the number provided by the "
"AGP 3.0 bridge!\n");
@@ -334,9 +334,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
arqsz = (tstatus >> 13) & 0x7;
- /*
+ /*
* Allocate a head for our AGP 3.5 device list
- * (multiple AGP v3 devices are allowed behind a single bridge).
+ * (multiple AGP v3 devices are allowed behind a single bridge).
*/
if ((dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
@@ -359,14 +359,15 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
case 0x0001: /* Unclassified device */
/* Don't know what this is, but log it for investigation. */
if (mcapndx != 0) {
- printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n",
- dev->vendor, dev->device);
+ dev_info(&td->dev, "wacky, found unclassified AGP device %s [%04x/%04x]\n",
+ pci_name(dev),
+ dev->vendor, dev->device);
}
continue;
case 0x0300: /* Display controller */
case 0x0400: /* Multimedia controller */
- if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) {
+ if ((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
goto free_and_exit;
}
@@ -391,7 +392,7 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
list_for_each(pos, head) {
cur = list_entry(pos, struct agp_3_5_dev, list);
dev = cur->dev;
-
+
pci_read_config_word(dev, PCI_STATUS, &mpstat);
if ((mpstat & PCI_STATUS_CAP_LIST) == 0)
continue;
@@ -407,17 +408,18 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
}
if (mcapndx == 0) {
- printk(KERN_ERR PFX "woah! Non-AGP device "
- "found on the secondary bus of an AGP 3.5 bridge!\n");
+ dev_err(&td->dev, "woah! Non-AGP device %s on "
+ "secondary bus of AGP 3.5 bridge!\n",
+ pci_name(dev));
ret = -ENODEV;
goto free_and_exit;
}
mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
if (mmajor < 3) {
- printk(KERN_ERR PFX "woah! AGP 2.0 device "
- "found on the secondary bus of an AGP 3.5 "
- "bridge operating with AGP 3.0 electricals!\n");
+ dev_err(&td->dev, "woah! AGP 2.0 device %s on "
+ "secondary bus of AGP 3.5 bridge operating "
+ "with AGP 3.0 electricals!\n", pci_name(dev));
ret = -ENODEV;
goto free_and_exit;
}
@@ -427,10 +429,10 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
pci_read_config_dword(dev, cur->capndx+AGPSTAT, &mstatus);
if (((mstatus >> 3) & 0x1) == 0) {
- printk(KERN_ERR PFX "woah! AGP 3.x device "
- "not operating in AGP 3.x mode found on the "
- "secondary bus of an AGP 3.5 bridge operating "
- "with AGP 3.0 electricals!\n");
+ dev_err(&td->dev, "woah! AGP 3.x device %s not "
+ "operating in AGP 3.x mode on secondary bus "
+ "of AGP 3.5 bridge operating with AGP 3.0 "
+ "electricals!\n", pci_name(dev));
ret = -ENODEV;
goto free_and_exit;
}
@@ -444,9 +446,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
if (isoch) {
ret = agp_3_5_isochronous_node_enable(bridge, dev_list, ndevs);
if (ret) {
- printk(KERN_INFO PFX "Something bad happened setting "
- "up isochronous xfers. Falling back to "
- "non-isochronous xfer mode.\n");
+ dev_info(&td->dev, "something bad happened setting "
+ "up isochronous xfers; falling back to "
+ "non-isochronous xfer mode\n");
} else {
goto free_and_exit;
}
@@ -466,4 +468,3 @@ free_and_exit:
get_out:
return ret;
}
-
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 80dafa3030b..a1861b75eb3 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -1,16 +1,16 @@
/*
* Nvidia AGPGART routines.
* Based upon a 2.4 agpgart diff by the folks from NVIDIA, and hacked up
- * to work in 2.5 by Dave Jones <davej@codemonkey.org.uk>
+ * to work in 2.5 by Dave Jones <davej@redhat.com>
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
-#include <linux/gfp.h>
#include <linux/page-flags.h>
#include <linux/mm.h>
+#include <linux/jiffies.h>
#include "agp.h"
/* NVIDIA registers */
@@ -72,7 +72,7 @@ static int nvidia_init_iorr(u32 base, u32 size)
/* Find the iorr that is already used for the base */
/* If not found, determine the uppermost available iorr */
free_iorr_addr = AMD_K7_NUM_IORR;
- for(iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) {
+ for (iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) {
rdmsr(IORR_BASE0 + 2 * iorr_addr, base_lo, base_hi);
rdmsr(IORR_MASK0 + 2 * iorr_addr, mask_lo, mask_hi);
@@ -82,7 +82,7 @@ static int nvidia_init_iorr(u32 base, u32 size)
if ((mask_lo & 0x00000800) == 0)
free_iorr_addr = iorr_addr;
}
-
+
if (iorr_addr >= AMD_K7_NUM_IORR) {
iorr_addr = free_iorr_addr;
if (iorr_addr >= AMD_K7_NUM_IORR)
@@ -106,6 +106,7 @@ static int nvidia_configure(void)
{
int i, rc, num_dirs;
u32 apbase, aplimit;
+ phys_addr_t apbase_phys;
struct aper_size_info_8 *current_size;
u32 temp;
@@ -115,9 +116,8 @@ static int nvidia_configure(void)
pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE,
current_size->size_value);
- /* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &apbase);
- apbase &= PCI_BASE_ADDRESS_MEM_MASK;
+ /* address to map to */
+ apbase = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
agp_bridge->gart_bus_addr = apbase;
aplimit = apbase + (current_size->size * 1024 * 1024) - 1;
pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APBASE, apbase);
@@ -139,7 +139,7 @@ static int nvidia_configure(void)
}
/* attbase */
- for(i = 0; i < 8; i++) {
+ for (i = 0; i < 8; i++) {
pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_ATTBASE(i),
(agp_bridge->gatt_bus_addr + (i % num_dirs) * 64 * 1024) | 1);
}
@@ -153,8 +153,12 @@ static int nvidia_configure(void)
pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp | 0x100);
/* map aperture */
+ apbase_phys = pci_resource_start(agp_bridge->dev, AGP_APERTURE_BAR);
nvidia_private.aperture =
- (volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE);
+ (volatile u32 __iomem *) ioremap(apbase_phys, 33 * PAGE_SIZE);
+
+ if (!nvidia_private.aperture)
+ return -ENOMEM;
return 0;
}
@@ -197,29 +201,37 @@ extern int agp_memory_reserved;
static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
{
int i, j;
-
- if ((type != 0) || (mem->type != 0))
+ int mask_type;
+
+ mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+ if (mask_type != 0 || type != mem->type)
return -EINVAL;
-
+
+ if (mem->page_count == 0)
+ return 0;
+
if ((pg_start + mem->page_count) >
(nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE))
return -EINVAL;
-
- for(j = pg_start; j < (pg_start + mem->page_count); j++) {
+
+ for (j = pg_start; j < (pg_start + mem->page_count); j++) {
if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j)))
return -EBUSY;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
global_cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mem->type),
+ page_to_phys(mem->pages[i]), mask_type),
agp_bridge->gatt_table+nvidia_private.pg_offset+j);
- readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j); /* PCI Posting. */
}
+
+ /* PCI Posting. */
+ readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j - 1);
+
agp_bridge->driver->tlb_flush(mem);
return 0;
}
@@ -229,9 +241,15 @@ static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type
{
int i;
- if ((type != 0) || (mem->type != 0))
+ int mask_type;
+
+ mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
+ if (mask_type != 0 || type != mem->type)
return -EINVAL;
+ if (mem->page_count == 0)
+ return 0;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++)
writel(agp_bridge->scratch_page, agp_bridge->gatt_table+nvidia_private.pg_offset+i);
@@ -256,7 +274,7 @@ static void nvidia_tlbflush(struct agp_memory *mem)
do {
pci_read_config_dword(nvidia_private.dev_1,
NVIDIA_1_WBC, &wbc_reg);
- if ((signed)(end - jiffies) <= 0) {
+ if (time_before_eq(end, jiffies)) {
printk(KERN_ERR PFX
"TLB flush took more than 3 seconds.\n");
}
@@ -264,14 +282,14 @@ static void nvidia_tlbflush(struct agp_memory *mem)
}
/* flush TLB entries */
- for(i = 0; i < 32 + 1; i++)
+ for (i = 0; i < 32 + 1; i++)
temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
- for(i = 0; i < 32 + 1; i++)
+ for (i = 0; i < 32 + 1; i++)
temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
}
-static struct aper_size_info_8 nvidia_generic_sizes[5] =
+static const struct aper_size_info_8 nvidia_generic_sizes[5] =
{
{512, 131072, 7, 0},
{256, 65536, 6, 8},
@@ -282,17 +300,18 @@ static struct aper_size_info_8 nvidia_generic_sizes[5] =
};
-static struct gatt_mask nvidia_generic_masks[] =
+static const struct gatt_mask nvidia_generic_masks[] =
{
{ .mask = 1, .type = 0}
};
-static struct agp_bridge_driver nvidia_driver = {
+static const struct agp_bridge_driver nvidia_driver = {
.owner = THIS_MODULE,
.aperture_sizes = nvidia_generic_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 5,
+ .needs_scratch_page = true,
.configure = nvidia_configure,
.fetch_size = nvidia_fetch_size,
.cleanup = nvidia_cleanup,
@@ -308,22 +327,25 @@ static struct agp_bridge_driver nvidia_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_nvidia_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
u8 cap_ptr;
nvidia_private.dev_1 =
- pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
+ pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
nvidia_private.dev_2 =
- pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
+ pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
nvidia_private.dev_3 =
- pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
-
+ pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
+
if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) {
printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 "
"chipset, but could not find the secondary devices.\n");
@@ -367,7 +389,7 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_nvidia_remove(struct pci_dev *pdev)
+static void agp_nvidia_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -375,6 +397,29 @@ static void __devexit agp_nvidia_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
+#ifdef CONFIG_PM
+static int agp_nvidia_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return 0;
+}
+
+static int agp_nvidia_resume(struct pci_dev *pdev)
+{
+ /* set power state 0 and restore PCI space */
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ /* reconfigure AGP hardware again */
+ nvidia_configure();
+
+ return 0;
+}
+#endif
+
+
static struct pci_device_id agp_nvidia_pci_table[] = {
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
@@ -402,6 +447,10 @@ static struct pci_driver agp_nvidia_pci_driver = {
.id_table = agp_nvidia_pci_table,
.probe = agp_nvidia_probe,
.remove = agp_nvidia_remove,
+#ifdef CONFIG_PM
+ .suspend = agp_nvidia_suspend,
+ .resume = agp_nvidia_resume,
+#endif
};
static int __init agp_nvidia_init(void)
@@ -414,6 +463,9 @@ static int __init agp_nvidia_init(void)
static void __exit agp_nvidia_cleanup(void)
{
pci_unregister_driver(&agp_nvidia_pci_driver);
+ pci_dev_put(nvidia_private.dev_1);
+ pci_dev_put(nvidia_private.dev_2);
+ pci_dev_put(nvidia_private.dev_3);
}
module_init(agp_nvidia_init);
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
new file mode 100644
index 00000000000..15f2e7025b7
--- /dev/null
+++ b/drivers/char/agp/parisc-agp.c
@@ -0,0 +1,426 @@
+/*
+ * HP Quicksilver AGP GART routines
+ *
+ * Copyright (c) 2006, Kyle McMartin <kyle@parisc-linux.org>
+ *
+ * Based on drivers/char/agpgart/hp-agp.c which is
+ * (c) Copyright 2002, 2003 Hewlett-Packard Development Company, L.P.
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/klist.h>
+#include <linux/agp_backend.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+
+#include <asm/parisc-device.h>
+#include <asm/ropes.h>
+
+#include "agp.h"
+
+#define DRVNAME "quicksilver"
+#define DRVPFX DRVNAME ": "
+
+#define AGP8X_MODE_BIT 3
+#define AGP8X_MODE (1 << AGP8X_MODE_BIT)
+
+static unsigned long
+parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
+ int type);
+
+static struct _parisc_agp_info {
+ void __iomem *ioc_regs;
+ void __iomem *lba_regs;
+
+ int lba_cap_offset;
+
+ u64 *gatt;
+ u64 gatt_entries;
+
+ u64 gart_base;
+ u64 gart_size;
+
+ int io_page_size;
+ int io_pages_per_kpage;
+} parisc_agp_info;
+
+static struct gatt_mask parisc_agp_masks[] =
+{
+ {
+ .mask = SBA_PDIR_VALID_BIT,
+ .type = 0
+ }
+};
+
+static struct aper_size_info_fixed parisc_agp_sizes[] =
+{
+ {0, 0, 0}, /* filled in by parisc_agp_fetch_size() */
+};
+
+static int
+parisc_agp_fetch_size(void)
+{
+ int size;
+
+ size = parisc_agp_info.gart_size / MB(1);
+ parisc_agp_sizes[0].size = size;
+ agp_bridge->current_size = (void *) &parisc_agp_sizes[0];
+
+ return size;
+}
+
+static int
+parisc_agp_configure(void)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+
+ agp_bridge->gart_bus_addr = info->gart_base;
+ agp_bridge->capndx = info->lba_cap_offset;
+ agp_bridge->mode = readl(info->lba_regs+info->lba_cap_offset+PCI_AGP_STATUS);
+
+ return 0;
+}
+
+static void
+parisc_agp_tlbflush(struct agp_memory *mem)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+
+ writeq(info->gart_base | ilog2(info->gart_size), info->ioc_regs+IOC_PCOM);
+ readq(info->ioc_regs+IOC_PCOM); /* flush */
+}
+
+static int
+parisc_agp_create_gatt_table(struct agp_bridge_data *bridge)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+ int i;
+
+ for (i = 0; i < info->gatt_entries; i++) {
+ info->gatt[i] = (unsigned long)agp_bridge->scratch_page;
+ }
+
+ return 0;
+}
+
+static int
+parisc_agp_free_gatt_table(struct agp_bridge_data *bridge)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+
+ info->gatt[0] = SBA_AGPGART_COOKIE;
+
+ return 0;
+}
+
+static int
+parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+ int i, k;
+ off_t j, io_pg_start;
+ int io_pg_count;
+
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
+ return -EINVAL;
+ }
+
+ io_pg_start = info->io_pages_per_kpage * pg_start;
+ io_pg_count = info->io_pages_per_kpage * mem->page_count;
+ if ((io_pg_start + io_pg_count) > info->gatt_entries) {
+ return -EINVAL;
+ }
+
+ j = io_pg_start;
+ while (j < (io_pg_start + io_pg_count)) {
+ if (info->gatt[j])
+ return -EBUSY;
+ j++;
+ }
+
+ if (!mem->is_flushed) {
+ global_cache_flush();
+ mem->is_flushed = true;
+ }
+
+ for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
+ unsigned long paddr;
+
+ paddr = page_to_phys(mem->pages[i]);
+ for (k = 0;
+ k < info->io_pages_per_kpage;
+ k++, j++, paddr += info->io_page_size) {
+ info->gatt[j] =
+ parisc_agp_mask_memory(agp_bridge,
+ paddr, type);
+ }
+ }
+
+ agp_bridge->driver->tlb_flush(mem);
+
+ return 0;
+}
+
+static int
+parisc_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+ int i, io_pg_start, io_pg_count;
+
+ if (type != mem->type ||
+ agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) {
+ return -EINVAL;
+ }
+
+ io_pg_start = info->io_pages_per_kpage * pg_start;
+ io_pg_count = info->io_pages_per_kpage * mem->page_count;
+ for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) {
+ info->gatt[i] = agp_bridge->scratch_page;
+ }
+
+ agp_bridge->driver->tlb_flush(mem);
+ return 0;
+}
+
+static unsigned long
+parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
+ int type)
+{
+ return SBA_PDIR_VALID_BIT | addr;
+}
+
+static void
+parisc_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+ u32 command;
+
+ command = readl(info->lba_regs + info->lba_cap_offset + PCI_AGP_STATUS);
+
+ command = agp_collect_device_status(bridge, mode, command);
+ command |= 0x00000100;
+
+ writel(command, info->lba_regs + info->lba_cap_offset + PCI_AGP_COMMAND);
+
+ agp_device_command(command, (mode & AGP8X_MODE) != 0);
+}
+
+static const struct agp_bridge_driver parisc_agp_driver = {
+ .owner = THIS_MODULE,
+ .size_type = FIXED_APER_SIZE,
+ .configure = parisc_agp_configure,
+ .fetch_size = parisc_agp_fetch_size,
+ .tlb_flush = parisc_agp_tlbflush,
+ .mask_memory = parisc_agp_mask_memory,
+ .masks = parisc_agp_masks,
+ .agp_enable = parisc_agp_enable,
+ .cache_flush = global_cache_flush,
+ .create_gatt_table = parisc_agp_create_gatt_table,
+ .free_gatt_table = parisc_agp_free_gatt_table,
+ .insert_memory = parisc_agp_insert_memory,
+ .remove_memory = parisc_agp_remove_memory,
+ .alloc_by_type = agp_generic_alloc_by_type,
+ .free_by_type = agp_generic_free_by_type,
+ .agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
+ .agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
+ .cant_use_aperture = true,
+};
+
+static int __init
+agp_ioc_init(void __iomem *ioc_regs)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+ u64 iova_base, *io_pdir, io_tlb_ps;
+ int io_tlb_shift;
+
+ printk(KERN_INFO DRVPFX "IO PDIR shared with sba_iommu\n");
+
+ info->ioc_regs = ioc_regs;
+
+ io_tlb_ps = readq(info->ioc_regs+IOC_TCNFG);
+ switch (io_tlb_ps) {
+ case 0: io_tlb_shift = 12; break;
+ case 1: io_tlb_shift = 13; break;
+ case 2: io_tlb_shift = 14; break;
+ case 3: io_tlb_shift = 16; break;
+ default:
+ printk(KERN_ERR DRVPFX "Invalid IOTLB page size "
+ "configuration 0x%llx\n", io_tlb_ps);
+ info->gatt = NULL;
+ info->gatt_entries = 0;
+ return -ENODEV;
+ }
+ info->io_page_size = 1 << io_tlb_shift;
+ info->io_pages_per_kpage = PAGE_SIZE / info->io_page_size;
+
+ iova_base = readq(info->ioc_regs+IOC_IBASE) & ~0x1;
+ info->gart_base = iova_base + PLUTO_IOVA_SIZE - PLUTO_GART_SIZE;
+
+ info->gart_size = PLUTO_GART_SIZE;
+ info->gatt_entries = info->gart_size / info->io_page_size;
+
+ io_pdir = phys_to_virt(readq(info->ioc_regs+IOC_PDIR_BASE));
+ info->gatt = &io_pdir[(PLUTO_IOVA_SIZE/2) >> PAGE_SHIFT];
+
+ if (info->gatt[0] != SBA_AGPGART_COOKIE) {
+ info->gatt = NULL;
+ info->gatt_entries = 0;
+ printk(KERN_ERR DRVPFX "No reserved IO PDIR entry found; "
+ "GART disabled\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int
+lba_find_capability(int cap)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+ u16 status;
+ u8 pos, id;
+ int ttl = 48;
+
+ status = readw(info->lba_regs + PCI_STATUS);
+ if (!(status & PCI_STATUS_CAP_LIST))
+ return 0;
+ pos = readb(info->lba_regs + PCI_CAPABILITY_LIST);
+ while (ttl-- && pos >= 0x40) {
+ pos &= ~3;
+ id = readb(info->lba_regs + pos + PCI_CAP_LIST_ID);
+ if (id == 0xff)
+ break;
+ if (id == cap)
+ return pos;
+ pos = readb(info->lba_regs + pos + PCI_CAP_LIST_NEXT);
+ }
+ return 0;
+}
+
+static int __init
+agp_lba_init(void __iomem *lba_hpa)
+{
+ struct _parisc_agp_info *info = &parisc_agp_info;
+ int cap;
+
+ info->lba_regs = lba_hpa;
+ info->lba_cap_offset = lba_find_capability(PCI_CAP_ID_AGP);
+
+ cap = readl(lba_hpa + info->lba_cap_offset) & 0xff;
+ if (cap != PCI_CAP_ID_AGP) {
+ printk(KERN_ERR DRVPFX "Invalid capability ID 0x%02x at 0x%x\n",
+ cap, info->lba_cap_offset);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int __init
+parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa)
+{
+ struct pci_dev *fake_bridge_dev = NULL;
+ struct agp_bridge_data *bridge;
+ int error = 0;
+
+ fake_bridge_dev = pci_alloc_dev(NULL);
+ if (!fake_bridge_dev) {
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ error = agp_ioc_init(ioc_hpa);
+ if (error)
+ goto fail;
+
+ error = agp_lba_init(lba_hpa);
+ if (error)
+ goto fail;
+
+ bridge = agp_alloc_bridge();
+ if (!bridge) {
+ error = -ENOMEM;
+ goto fail;
+ }
+ bridge->driver = &parisc_agp_driver;
+
+ fake_bridge_dev->vendor = PCI_VENDOR_ID_HP;
+ fake_bridge_dev->device = PCI_DEVICE_ID_HP_PCIX_LBA;
+ bridge->dev = fake_bridge_dev;
+
+ error = agp_add_bridge(bridge);
+ if (error)
+ goto fail;
+ return 0;
+
+fail:
+ kfree(fake_bridge_dev);
+ return error;
+}
+
+static int
+find_quicksilver(struct device *dev, void *data)
+{
+ struct parisc_device **lba = data;
+ struct parisc_device *padev = to_parisc_device(dev);
+
+ if (IS_QUICKSILVER(padev))
+ *lba = padev;
+
+ return 0;
+}
+
+static int
+parisc_agp_init(void)
+{
+ extern struct sba_device *sba_list;
+
+ int err = -1;
+ struct parisc_device *sba = NULL, *lba = NULL;
+ struct lba_device *lbadev = NULL;
+
+ if (!sba_list)
+ goto out;
+
+ /* Find our parent Pluto */
+ sba = sba_list->dev;
+ if (!IS_PLUTO(sba)) {
+ printk(KERN_INFO DRVPFX "No Pluto found, so no AGPGART for you.\n");
+ goto out;
+ }
+
+ /* Now search our Pluto for our precious AGP device... */
+ device_for_each_child(&sba->dev, &lba, find_quicksilver);
+
+ if (!lba) {
+ printk(KERN_INFO DRVPFX "No AGP devices found.\n");
+ goto out;
+ }
+
+ lbadev = parisc_get_drvdata(lba);
+
+ /* w00t, let's go find our cookies... */
+ parisc_agp_setup(sba_list->ioc[0].ioc_hpa, lbadev->hba.base_addr);
+
+ return 0;
+
+out:
+ return err;
+}
+
+module_init(parisc_agp_init);
+
+MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 4df7734b51c..3051c73bc38 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -14,7 +14,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/agp_backend.h>
#include <asm/sn/addrs.h>
#include <asm/sn/io.h>
@@ -38,7 +38,7 @@ static struct aper_size_info_fixed sgi_tioca_sizes[] = {
{0, 0, 0},
};
-static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
+static struct page *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
{
struct page *page;
int nid;
@@ -47,14 +47,12 @@ static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
nid = info->ca_closest_node;
page = alloc_pages_node(nid, GFP_KERNEL, 0);
- if (page == NULL) {
- return 0;
- }
+ if (!page)
+ return NULL;
get_page(page);
- SetPageLocked(page);
atomic_inc(&agp_bridge->current_memory_agp);
- return page_address(page);
+ return page;
}
/*
@@ -72,8 +70,8 @@ static void sgi_tioca_tlbflush(struct agp_memory *mem)
* entry.
*/
static unsigned long
-sgi_tioca_mask_memory(struct agp_bridge_data *bridge,
- unsigned long addr, int type)
+sgi_tioca_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
+ int type)
{
return tioca_physpage_to_gart(addr);
}
@@ -159,7 +157,6 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
break;
case LVL2_APER_SIZE:
return -EINVAL;
- break;
default:
num_entries = 0;
break;
@@ -184,14 +181,15 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
j++;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
bridge->driver->cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
table[j] =
- bridge->driver->mask_memory(bridge, mem->memory[i],
+ bridge->driver->mask_memory(bridge,
+ page_to_phys(mem->pages[i]),
mem->type);
}
@@ -247,7 +245,7 @@ static struct agp_bridge_data *sgi_tioca_find_bridge(struct pci_dev *pdev)
return bridge;
}
-struct agp_bridge_driver sgi_tioca_driver = {
+const struct agp_bridge_driver sgi_tioca_driver = {
.owner = THIS_MODULE,
.size_type = U16_APER_SIZE,
.configure = sgi_tioca_configure,
@@ -265,12 +263,13 @@ struct agp_bridge_driver sgi_tioca_driver = {
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = sgi_tioca_alloc_page,
.agp_destroy_page = agp_generic_destroy_page,
- .cant_use_aperture = 1,
- .needs_scratch_page = 0,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
+ .cant_use_aperture = true,
+ .needs_scratch_page = false,
.num_aperture_sizes = 1,
};
-static int __devinit agp_sgi_init(void)
+static int agp_sgi_init(void)
{
unsigned int j;
struct tioca_kernel *info;
@@ -281,19 +280,19 @@ static int __devinit agp_sgi_init(void)
else
return 0;
- sgi_tioca_agp_bridges =
- (struct agp_bridge_data **)kmalloc(tioca_gart_found *
- sizeof(struct agp_bridge_data *),
- GFP_KERNEL);
+ sgi_tioca_agp_bridges = kmalloc(tioca_gart_found *
+ sizeof(struct agp_bridge_data *),
+ GFP_KERNEL);
+ if (!sgi_tioca_agp_bridges)
+ return -ENOMEM;
j = 0;
list_for_each_entry(info, &tioca_list, ca_list) {
- struct list_head *tmp;
if (list_empty(info->ca_devices))
continue;
- list_for_each(tmp, info->ca_devices) {
+ list_for_each_entry(pdev, info->ca_devices, bus_list) {
u8 cap_ptr;
- pdev = pci_dev_b(tmp);
+
if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
continue;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
@@ -327,11 +326,10 @@ static int __devinit agp_sgi_init(void)
return 0;
}
-static void __devexit agp_sgi_cleanup(void)
+static void agp_sgi_cleanup(void)
{
- if(sgi_tioca_agp_bridges)
- kfree(sgi_tioca_agp_bridges);
- sgi_tioca_agp_bridges=NULL;
+ kfree(sgi_tioca_agp_bridges);
+ sgi_tioca_agp_bridges = NULL;
}
module_init(agp_sgi_init);
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index ebc05554045..2c74038da45 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -14,8 +14,11 @@
#define SIS_TLBCNTRL 0x97
#define SIS_TLBFLUSH 0x98
-static int __devinitdata agp_sis_force_delay = 0;
-static int __devinitdata agp_sis_agp_spec = -1;
+#define PCI_DEVICE_ID_SI_662 0x0662
+#define PCI_DEVICE_ID_SI_671 0x0671
+
+static bool agp_sis_force_delay = 0;
+static int agp_sis_agp_spec = -1;
static int sis_fetch_size(void)
{
@@ -27,8 +30,8 @@ static int sis_fetch_size(void)
values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
if ((temp_size == values[i].size_value) ||
- ((temp_size & ~(0x03)) ==
- (values[i].size_value & ~(0x03)))) {
+ ((temp_size & ~(0x07)) ==
+ (values[i].size_value & ~(0x07)))) {
agp_bridge->previous_size =
agp_bridge->current_size = (void *) (values + i);
@@ -47,13 +50,12 @@ static void sis_tlbflush(struct agp_memory *mem)
static int sis_configure(void)
{
- u32 temp;
struct aper_size_info_8 *current_size;
current_size = A_SIZE_8(agp_bridge->current_size);
pci_write_config_byte(agp_bridge->dev, SIS_TLBCNTRL, 0x05);
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
pci_write_config_dword(agp_bridge->dev, SIS_ATTBASE,
agp_bridge->gatt_bus_addr);
pci_write_config_byte(agp_bridge->dev, SIS_APSIZE,
@@ -76,10 +78,8 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
u32 command;
int rate;
- printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",
- agp_bridge->major_version,
- agp_bridge->minor_version,
- pci_name(agp_bridge->dev));
+ dev_info(&agp_bridge->dev->dev, "AGP %d.%d bridge\n",
+ agp_bridge->major_version, agp_bridge->minor_version);
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command);
command = agp_collect_device_status(bridge, mode, command);
@@ -91,8 +91,8 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
if (!agp)
continue;
- printk(KERN_INFO PFX "Putting AGP V3 device at %s into %dx mode\n",
- pci_name(device), rate);
+ dev_info(&agp_bridge->dev->dev, "putting AGP V3 device at %s into %dx mode\n",
+ pci_name(device), rate);
pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
@@ -102,13 +102,13 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
* cannot be configured
*/
if (device->device == bridge->dev->device) {
- printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n");
+ dev_info(&agp_bridge->dev->dev, "SiS delay workaround: giving bridge time to recover\n");
msleep(10);
}
}
}
-static struct aper_size_info_8 sis_generic_sizes[7] =
+static const struct aper_size_info_8 sis_generic_sizes[7] =
{
{256, 65536, 6, 99},
{128, 32768, 5, 83},
@@ -121,9 +121,10 @@ static struct aper_size_info_8 sis_generic_sizes[7] =
static struct agp_bridge_driver sis_driver = {
.owner = THIS_MODULE,
- .aperture_sizes = sis_generic_sizes,
+ .aperture_sizes = sis_generic_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 7,
+ .needs_scratch_page = true,
.configure = sis_configure,
.fetch_size = sis_fetch_size,
.cleanup = sis_cleanup,
@@ -139,115 +140,28 @@ static struct agp_bridge_driver sis_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
-{
- {
- .device_id = PCI_DEVICE_ID_SI_5591_AGP,
- .chipset_name = "5591",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_530,
- .chipset_name = "530",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_540,
- .chipset_name = "540",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_550,
- .chipset_name = "550",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_620,
- .chipset_name = "620",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_630,
- .chipset_name = "630",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_635,
- .chipset_name = "635",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_645,
- .chipset_name = "645",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_646,
- .chipset_name = "646",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_648,
- .chipset_name = "648",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_650,
- .chipset_name = "650",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_651,
- .chipset_name = "651",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_655,
- .chipset_name = "655",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_661,
- .chipset_name = "661",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_730,
- .chipset_name = "730",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_735,
- .chipset_name = "735",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_740,
- .chipset_name = "740",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_741,
- .chipset_name = "741",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_745,
- .chipset_name = "745",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_746,
- .chipset_name = "746",
- },
- {
- .device_id = PCI_DEVICE_ID_SI_760,
- .chipset_name = "760",
- },
- { }, /* dummy final entry, always present */
-};
-
-
// chipsets that require the 'delay hack'
-static int sis_broken_chipsets[] __devinitdata = {
+static int sis_broken_chipsets[] = {
PCI_DEVICE_ID_SI_648,
PCI_DEVICE_ID_SI_746,
0 // terminator
};
-static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
+static void sis_get_driver(struct agp_bridge_data *bridge)
{
int i;
- for(i=0; sis_broken_chipsets[i]!=0; ++i)
- if(bridge->dev->device==sis_broken_chipsets[i])
+ for (i=0; sis_broken_chipsets[i]!=0; ++i)
+ if (bridge->dev->device==sis_broken_chipsets[i])
break;
- if(sis_broken_chipsets[i] || agp_sis_force_delay)
+ if (sis_broken_chipsets[i] || agp_sis_force_delay)
sis_driver.agp_enable=sis_delayed_enable;
// sis chipsets that indicate less than agp3.5
@@ -265,32 +179,18 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge)
}
-static int __devinit agp_sis_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_sis_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- struct agp_device_ids *devs = sis_agp_device_ids;
struct agp_bridge_data *bridge;
u8 cap_ptr;
- int j;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
if (!cap_ptr)
return -ENODEV;
- /* probe for known chipsets */
- for (j = 0; devs[j].chipset_name; j++) {
- if (pdev->device == devs[j].device_id) {
- printk(KERN_INFO PFX "Detected SiS %s chipset\n",
- devs[j].chipset_name);
- goto found;
- }
- }
-
- printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n",
- pdev->device);
- return -ENODEV;
-found:
+ dev_info(&pdev->dev, "SiS chipset [%04x/%04x]\n",
+ pdev->vendor, pdev->device);
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
@@ -309,7 +209,7 @@ found:
return agp_add_bridge(bridge);
}
-static void __devexit agp_sis_remove(struct pci_dev *pdev)
+static void agp_sis_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -317,14 +217,202 @@ static void __devexit agp_sis_remove(struct pci_dev *pdev)
agp_put_bridge(bridge);
}
+#ifdef CONFIG_PM
+
+static int agp_sis_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int agp_sis_resume(struct pci_dev *pdev)
+{
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ return sis_driver.configure();
+}
+
+#endif /* CONFIG_PM */
+
static struct pci_device_id agp_sis_pci_table[] = {
{
- .class = (PCI_CLASS_BRIDGE_HOST << 8),
- .class_mask = ~0,
- .vendor = PCI_VENDOR_ID_SI,
- .device = PCI_ANY_ID,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_5591,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_530,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_540,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_550,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_620,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_630,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_635,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_645,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_646,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_648,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_650,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_651,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_655,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_661,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_662,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_671,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_730,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_735,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_740,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_741,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_745,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_746,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
},
{ }
};
@@ -336,6 +424,10 @@ static struct pci_driver agp_sis_pci_driver = {
.id_table = agp_sis_pci_table,
.probe = agp_sis_probe,
.remove = agp_sis_remove,
+#ifdef CONFIG_PM
+ .suspend = agp_sis_suspend,
+ .resume = agp_sis_resume,
+#endif
};
static int __init agp_sis_init(void)
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 268f78d926d..9b163b49d97 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -52,28 +52,20 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map)
if (page_map->real == NULL) {
return -ENOMEM;
}
- SetPageReserved(virt_to_page(page_map->real));
- global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
- PAGE_SIZE);
- if (page_map->remapped == NULL) {
- ClearPageReserved(virt_to_page(page_map->real));
- free_page((unsigned long) page_map->real);
- page_map->real = NULL;
- return -ENOMEM;
- }
- global_cache_flush();
- for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
+ set_memory_uc((unsigned long)page_map->real, 1);
+ page_map->remapped = page_map->real;
+
+ for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
writel(agp_bridge->scratch_page, page_map->remapped+i);
+ /* Red Pen: Everyone else does pci posting flush here */
return 0;
}
static void serverworks_free_page_map(struct serverworks_page_map *page_map)
{
- iounmap(page_map->remapped);
- ClearPageReserved(virt_to_page(page_map->real));
+ set_memory_wb((unsigned long)page_map->real, 1);
free_page((unsigned long) page_map->real);
}
@@ -84,7 +76,7 @@ static void serverworks_free_gatt_pages(void)
struct serverworks_page_map *entry;
tables = serverworks_private.gatt_pages;
- for(i = 0; i < serverworks_private.num_tables; i++) {
+ for (i = 0; i < serverworks_private.num_tables; i++) {
entry = tables[i];
if (entry != NULL) {
if (entry->real != NULL) {
@@ -103,7 +95,7 @@ static int serverworks_create_gatt_pages(int nr_tables)
int retval = 0;
int i;
- tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *),
+ tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *),
GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
@@ -161,9 +153,9 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
return retval;
}
/* Create a fake scratch directory */
- for(i = 0; i < 1024; i++) {
+ for (i = 0; i < 1024; i++) {
writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
- writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+ writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
}
retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -175,7 +167,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -185,10 +177,9 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
pci_read_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,&temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- /* Calculate the agp offset */
-
- for(i = 0; i < value->num_entries / 1024; i++)
- writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+ /* Calculate the agp offset */
+ for (i = 0; i < value->num_entries / 1024; i++)
+ writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
return 0;
}
@@ -196,7 +187,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
static int serverworks_free_gatt_table(struct agp_bridge_data *bridge)
{
struct serverworks_page_map page_dir;
-
+
page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
@@ -238,7 +229,7 @@ static int serverworks_fetch_size(void)
* This routine could be implemented by taking the addresses
* written to the GATT, and flushing them individually. However
* currently it just flushes the whole table. Which is probably
- * more efficent, since agp_memory blocks can be a large number of
+ * more efficient, since agp_memory blocks can be a large number of
* entries.
*/
static void serverworks_tlbflush(struct agp_memory *temp)
@@ -250,7 +241,8 @@ static void serverworks_tlbflush(struct agp_memory *temp)
while (readb(serverworks_private.registers+SVWRKS_POSTFLUSH) == 1) {
cpu_relax();
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR PFX "TLB post flush took more than 3 seconds\n");
+ dev_err(&serverworks_private.svrwrks_dev->dev,
+ "TLB post flush took more than 3 seconds\n");
break;
}
}
@@ -260,7 +252,8 @@ static void serverworks_tlbflush(struct agp_memory *temp)
while (readl(serverworks_private.registers+SVWRKS_DIRFLUSH) == 1) {
cpu_relax();
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR PFX "TLB Dir flush took more than 3 seconds\n");
+ dev_err(&serverworks_private.svrwrks_dev->dev,
+ "TLB Dir flush took more than 3 seconds\n");
break;
}
}
@@ -280,7 +273,7 @@ static int serverworks_configure(void)
temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
serverworks_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
if (!serverworks_private.registers) {
- printk (KERN_ERR PFX "Unable to ioremap() memory.\n");
+ dev_err(&agp_bridge->dev->dev, "can't ioremap(%#x)\n", temp);
return -ENOMEM;
}
@@ -348,15 +341,17 @@ static int serverworks_insert_memory(struct agp_memory *mem,
j++;
}
- if (mem->is_flushed == FALSE) {
+ if (!mem->is_flushed) {
global_cache_flush();
- mem->is_flushed = TRUE;
+ mem->is_flushed = true;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = SVRWRKS_GET_GATT(addr);
- writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ page_to_phys(mem->pages[i]), mem->type),
+ cur_gatt+GET_GATT_OFF(addr));
}
serverworks_tlbflush(mem);
return 0;
@@ -386,12 +381,12 @@ static int serverworks_remove_memory(struct agp_memory *mem, off_t pg_start,
return 0;
}
-static struct gatt_mask serverworks_masks[] =
+static const struct gatt_mask serverworks_masks[] =
{
{.mask = 1, .type = 0}
};
-static struct aper_size_info_lvl2 serverworks_sizes[7] =
+static const struct aper_size_info_lvl2 serverworks_sizes[7] =
{
{2048, 524288, 0x80000000},
{1024, 262144, 0xc0000000},
@@ -421,10 +416,10 @@ static void serverworks_agp_enable(struct agp_bridge_data *bridge, u32 mode)
bridge->capndx + PCI_AGP_COMMAND,
command);
- agp_device_command(command, 0);
+ agp_device_command(command, false);
}
-static struct agp_bridge_driver sworks_driver = {
+static const struct agp_bridge_driver sworks_driver = {
.owner = THIS_MODULE,
.aperture_sizes = serverworks_sizes,
.size_type = LVL2_APER_SIZE,
@@ -444,33 +439,25 @@ static struct agp_bridge_driver sworks_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_serverworks_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
struct pci_dev *bridge_dev;
u32 temp, temp2;
u8 cap_ptr = 0;
- /* Everything is on func 1 here so we are hardcoding function one */
- bridge_dev = pci_find_slot((unsigned int)pdev->bus->number,
- PCI_DEVFN(0, 1));
- if (!bridge_dev) {
- printk(KERN_INFO PFX "Detected a Serverworks chipset "
- "but could not find the secondary device.\n");
- return -ENODEV;
- }
-
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
switch (pdev->device) {
case 0x0006:
- /* ServerWorks CNB20HE
- Fail silently.*/
- printk (KERN_ERR PFX "Detected ServerWorks CNB20HE chipset: No AGP present.\n");
+ dev_err(&pdev->dev, "ServerWorks CNB20HE is unsupported due to lack of documentation\n");
return -ENODEV;
case PCI_DEVICE_ID_SERVERWORKS_HE:
@@ -480,8 +467,16 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
default:
if (cap_ptr)
- printk(KERN_ERR PFX "Unsupported Serverworks chipset "
- "(device id: %04x)\n", pdev->device);
+ dev_err(&pdev->dev, "unsupported Serverworks chipset "
+ "[%04x/%04x]\n", pdev->vendor, pdev->device);
+ return -ENODEV;
+ }
+
+ /* Everything is on func 1 here so we are hardcoding function one */
+ bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
+ PCI_DEVFN(0, 1));
+ if (!bridge_dev) {
+ dev_info(&pdev->dev, "can't find secondary device\n");
return -ENODEV;
}
@@ -492,8 +487,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) {
pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2);
if (temp2 != 0) {
- printk(KERN_INFO PFX "Detected 64 bit aperture address, "
- "but top bits are not zero. Disabling agp\n");
+ dev_info(&pdev->dev, "64 bit aperture address, "
+ "but top bits are not zero; disabling AGP\n");
return -ENODEV;
}
serverworks_private.mm_addr_ofs = 0x18;
@@ -505,8 +500,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
pci_read_config_dword(pdev,
serverworks_private.mm_addr_ofs + 4, &temp2);
if (temp2 != 0) {
- printk(KERN_INFO PFX "Detected 64 bit MMIO address, "
- "but top bits are not zero. Disabling agp\n");
+ dev_info(&pdev->dev, "64 bit MMIO address, but top "
+ "bits are not zero; disabling AGP\n");
return -ENODEV;
}
}
@@ -517,18 +512,21 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev,
bridge->driver = &sworks_driver;
bridge->dev_private_data = &serverworks_private,
- bridge->dev = pdev;
+ bridge->dev = pci_dev_get(pdev);
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
}
-static void __devexit agp_serverworks_remove(struct pci_dev *pdev)
+static void agp_serverworks_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+ pci_dev_put(bridge->dev);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
+ pci_dev_put(serverworks_private.svrwrks_dev);
+ serverworks_private.svrwrks_dev = NULL;
}
static struct pci_device_id agp_serverworks_pci_table[] = {
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 50947e38501..a56ee9bedd1 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -3,10 +3,12 @@
*/
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/slab.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/agp_backend.h>
#include <linux/delay.h>
+#include <linux/vmalloc.h>
#include <asm/uninorth.h>
#include <asm/pci-bridge.h>
#include <asm/prom.h>
@@ -26,33 +28,46 @@
*/
static int uninorth_rev;
static int is_u3;
+static u32 scratch_value;
+#define DEFAULT_APERTURE_SIZE 256
+#define DEFAULT_APERTURE_STRING "256"
+static char *aperture = NULL;
static int uninorth_fetch_size(void)
{
- int i;
- u32 temp;
- struct aper_size_info_32 *values;
-
- pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_BASE, &temp);
- temp &= ~(0xfffff000);
- values = A_SIZE_32(agp_bridge->driver->aperture_sizes);
-
- for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
- if (temp == values[i].size_value) {
- agp_bridge->previous_size =
- agp_bridge->current_size = (void *) (values + i);
- agp_bridge->aperture_size_idx = i;
- return values[i].size;
+ int i, size = 0;
+ struct aper_size_info_32 *values =
+ A_SIZE_32(agp_bridge->driver->aperture_sizes);
+
+ if (aperture) {
+ char *save = aperture;
+
+ size = memparse(aperture, &aperture) >> 20;
+ aperture = save;
+
+ for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
+ if (size == values[i].size)
+ break;
+
+ if (i == agp_bridge->driver->num_aperture_sizes) {
+ dev_err(&agp_bridge->dev->dev, "invalid aperture size, "
+ "using default\n");
+ size = 0;
+ aperture = NULL;
}
}
- agp_bridge->previous_size =
- agp_bridge->current_size = (void *) (values + 1);
- agp_bridge->aperture_size_idx = 1;
- return values[1].size;
+ if (!size) {
+ for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++)
+ if (values[i].size == DEFAULT_APERTURE_SIZE)
+ break;
+ }
- return 0;
+ agp_bridge->previous_size =
+ agp_bridge->current_size = (void *)(values + i);
+ agp_bridge->aperture_size_idx = i;
+ return values[i].size;
}
static void uninorth_tlbflush(struct agp_memory *mem)
@@ -65,7 +80,7 @@ static void uninorth_tlbflush(struct agp_memory *mem)
ctrl | UNI_N_CFG_GART_INVAL);
pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, ctrl);
- if (uninorth_rev <= 0x30) {
+ if (!mem && uninorth_rev <= 0x30) {
pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
ctrl | UNI_N_CFG_GART_2xRESET);
pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
@@ -95,12 +110,12 @@ static void uninorth_cleanup(void)
static int uninorth_configure(void)
{
struct aper_size_info_32 *current_size;
-
+
current_size = A_SIZE_32(agp_bridge->current_size);
- printk(KERN_INFO PFX "configuring for size idx: %d\n",
- current_size->size_value);
-
+ dev_info(&agp_bridge->dev->dev, "configuring for size idx: %d\n",
+ current_size->size_value);
+
/* aperture size and gatt addr */
pci_write_config_dword(agp_bridge->dev,
UNI_N_CFG_GART_BASE,
@@ -125,100 +140,85 @@ static int uninorth_configure(void)
if (is_u3) {
pci_write_config_dword(agp_bridge->dev,
UNI_N_CFG_GART_DUMMY_PAGE,
- agp_bridge->scratch_page_real >> 12);
+ page_to_phys(agp_bridge->scratch_page_page) >> 12);
}
-
+
return 0;
}
-static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
- int type)
+static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
{
- int i, j, num_entries;
+ int i, num_entries;
void *temp;
+ u32 *gp;
+ int mask_type;
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_32(temp)->num_entries;
+ if (type != mem->type)
+ return -EINVAL;
- if (type != 0 || mem->type != 0)
+ mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+ if (mask_type != 0) {
/* We know nothing of memory types */
return -EINVAL;
- if ((pg_start + mem->page_count) > num_entries)
- return -EINVAL;
-
- j = pg_start;
-
- while (j < (pg_start + mem->page_count)) {
- if (agp_bridge->gatt_table[j])
- return -EBUSY;
- j++;
- }
-
- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- agp_bridge->gatt_table[j] =
- cpu_to_le32((mem->memory[i] & 0xFFFFF000UL) | 0x1UL);
- flush_dcache_range((unsigned long)__va(mem->memory[i]),
- (unsigned long)__va(mem->memory[i])+0x1000);
}
- (void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]);
- mb();
- flush_dcache_range((unsigned long)&agp_bridge->gatt_table[pg_start],
- (unsigned long)&agp_bridge->gatt_table[pg_start + mem->page_count]);
-
- uninorth_tlbflush(mem);
- return 0;
-}
-static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
-{
- int i, num_entries;
- void *temp;
- u32 *gp;
+ if (mem->page_count == 0)
+ return 0;
temp = agp_bridge->current_size;
num_entries = A_SIZE_32(temp)->num_entries;
- if (type != 0 || mem->type != 0)
- /* We know nothing of memory types */
- return -EINVAL;
if ((pg_start + mem->page_count) > num_entries)
return -EINVAL;
gp = (u32 *) &agp_bridge->gatt_table[pg_start];
for (i = 0; i < mem->page_count; ++i) {
- if (gp[i]) {
- printk("u3_insert_memory: entry 0x%x occupied (%x)\n",
- i, gp[i]);
+ if (gp[i] != scratch_value) {
+ dev_info(&agp_bridge->dev->dev,
+ "uninorth_insert_memory: entry 0x%x occupied (%x)\n",
+ i, gp[i]);
return -EBUSY;
}
}
for (i = 0; i < mem->page_count; i++) {
- gp[i] = (mem->memory[i] >> PAGE_SHIFT) | 0x80000000UL;
- flush_dcache_range((unsigned long)__va(mem->memory[i]),
- (unsigned long)__va(mem->memory[i])+0x1000);
+ if (is_u3)
+ gp[i] = (page_to_phys(mem->pages[i]) >> PAGE_SHIFT) | 0x80000000UL;
+ else
+ gp[i] = cpu_to_le32((page_to_phys(mem->pages[i]) & 0xFFFFF000UL) |
+ 0x1UL);
+ flush_dcache_range((unsigned long)__va(page_to_phys(mem->pages[i])),
+ (unsigned long)__va(page_to_phys(mem->pages[i]))+0x1000);
}
mb();
- flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
uninorth_tlbflush(mem);
return 0;
}
-int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
+int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
{
size_t i;
u32 *gp;
+ int mask_type;
+
+ if (type != mem->type)
+ return -EINVAL;
- if (type != 0 || mem->type != 0)
+ mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
+ if (mask_type != 0) {
/* We know nothing of memory types */
return -EINVAL;
+ }
+
+ if (mem->page_count == 0)
+ return 0;
gp = (u32 *) &agp_bridge->gatt_table[pg_start];
- for (i = 0; i < mem->page_count; ++i)
- gp[i] = 0;
+ for (i = 0; i < mem->page_count; ++i) {
+ gp[i] = scratch_value;
+ }
mb();
- flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
uninorth_tlbflush(mem);
return 0;
@@ -235,7 +235,7 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
command = agp_collect_device_status(bridge, mode, status);
command |= PCI_AGP_COMMAND_AGP;
-
+
if (uninorth_rev == 0x21) {
/*
* Darwin disable AGP 4x on this revision, thus we
@@ -246,7 +246,7 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
/*
- * We need to to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
+ * We need to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
* 2.2 and 2.3, Darwin do so.
*/
if ((command >> AGPSTAT_RQ_DEPTH_SHIFT) > 7)
@@ -266,15 +266,15 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
&scratch);
} while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000);
if ((scratch & PCI_AGP_COMMAND_AGP) == 0)
- printk(KERN_ERR PFX "failed to write UniNorth AGP"
- " command register\n");
+ dev_err(&bridge->dev->dev, "can't write UniNorth AGP "
+ "command register\n");
if (uninorth_rev >= 0x30) {
/* This is an AGP V3 */
- agp_device_command(command, (status & AGPSTAT_MODE_3_0));
+ agp_device_command(command, (status & AGPSTAT_MODE_3_0) != 0);
} else {
/* AGP V2 */
- agp_device_command(command, 0);
+ agp_device_command(command, false);
}
uninorth_tlbflush(NULL);
@@ -320,8 +320,8 @@ static int agp_uninorth_suspend(struct pci_dev *pdev)
pci_read_config_dword(device, agp + PCI_AGP_COMMAND, &cmd);
if (!(cmd & PCI_AGP_COMMAND_AGP))
continue;
- printk("uninorth-agp: disabling AGP on device %s\n",
- pci_name(device));
+ dev_info(&pdev->dev, "disabling AGP on device %s\n",
+ pci_name(device));
cmd &= ~PCI_AGP_COMMAND_AGP;
pci_write_config_dword(device, agp + PCI_AGP_COMMAND, cmd);
}
@@ -329,10 +329,9 @@ static int agp_uninorth_suspend(struct pci_dev *pdev)
/* turn off AGP on the bridge */
agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
- bridge->dev_private_data = (void *)cmd;
+ bridge->dev_private_data = (void *)(long)cmd;
if (cmd & PCI_AGP_COMMAND_AGP) {
- printk("uninorth-agp: disabling AGP on bridge %s\n",
- pci_name(pdev));
+ dev_info(&pdev->dev, "disabling AGP on bridge\n");
cmd &= ~PCI_AGP_COMMAND_AGP;
pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND, cmd);
}
@@ -351,7 +350,7 @@ static int agp_uninorth_resume(struct pci_dev *pdev)
if (bridge == NULL)
return -ENODEV;
- command = (u32)bridge->dev_private_data;
+ command = (long)bridge->dev_private_data;
bridge->dev_private_data = NULL;
if (!(command & PCI_AGP_COMMAND_AGP))
return 0;
@@ -372,6 +371,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
int i;
void *temp;
struct page *page;
+ struct page **pages;
/* We can't handle 2 level gatt's */
if (bridge->driver->size_type == LVL2_APER_SIZE)
@@ -400,21 +400,44 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
if (table == NULL)
return -ENOMEM;
+ pages = kmalloc((1 << page_order) * sizeof(struct page*), GFP_KERNEL);
+ if (pages == NULL)
+ goto enomem;
+
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
- for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
+ for (page = virt_to_page(table), i = 0; page <= virt_to_page(table_end);
+ page++, i++) {
SetPageReserved(page);
+ pages[i] = page;
+ }
bridge->gatt_table_real = (u32 *) table;
- bridge->gatt_table = (u32 *)table;
- bridge->gatt_bus_addr = virt_to_gart(table);
+ /* Need to clear out any dirty data still sitting in caches */
+ flush_dcache_range((unsigned long)table,
+ (unsigned long)table_end + 1);
+ bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG);
- for (i = 0; i < num_entries; i++)
- bridge->gatt_table[i] = 0;
+ if (bridge->gatt_table == NULL)
+ goto enomem;
- flush_dcache_range((unsigned long)table, (unsigned long)table_end);
+ bridge->gatt_bus_addr = virt_to_phys(table);
+
+ if (is_u3)
+ scratch_value = (page_to_phys(agp_bridge->scratch_page_page) >> PAGE_SHIFT) | 0x80000000UL;
+ else
+ scratch_value = cpu_to_le32((page_to_phys(agp_bridge->scratch_page_page) & 0xFFFFF000UL) |
+ 0x1UL);
+ for (i = 0; i < num_entries; i++)
+ bridge->gatt_table[i] = scratch_value;
return 0;
+
+enomem:
+ kfree(pages);
+ if (table)
+ free_pages((unsigned long)table, page_order);
+ return -ENOMEM;
}
static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
@@ -432,6 +455,7 @@ static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
* from the table.
*/
+ vunmap(bridge->gatt_table);
table = (char *) bridge->gatt_table_real;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
@@ -450,13 +474,11 @@ void null_cache_flush(void)
/* Setup function */
-static struct aper_size_info_32 uninorth_sizes[7] =
+static const struct aper_size_info_32 uninorth_sizes[] =
{
-#if 0 /* Not sure uninorth supports that high aperture sizes */
{256, 65536, 6, 64},
{128, 32768, 5, 32},
{64, 16384, 4, 16},
-#endif
{32, 8192, 3, 8},
{16, 4096, 2, 4},
{8, 2048, 1, 2},
@@ -467,7 +489,7 @@ static struct aper_size_info_32 uninorth_sizes[7] =
* Not sure that u3 supports that high aperture sizes but it
* would strange if it did not :)
*/
-static struct aper_size_info_32 u3_sizes[8] =
+static const struct aper_size_info_32 u3_sizes[] =
{
{512, 131072, 7, 128},
{256, 65536, 6, 64},
@@ -479,11 +501,11 @@ static struct aper_size_info_32 u3_sizes[8] =
{4, 1024, 0, 1}
};
-struct agp_bridge_driver uninorth_agp_driver = {
+const struct agp_bridge_driver uninorth_agp_driver = {
.owner = THIS_MODULE,
.aperture_sizes = (void *)uninorth_sizes,
.size_type = U32_APER_SIZE,
- .num_aperture_sizes = 4,
+ .num_aperture_sizes = ARRAY_SIZE(uninorth_sizes),
.configure = uninorth_configure,
.fetch_size = uninorth_fetch_size,
.cleanup = uninorth_cleanup,
@@ -495,19 +517,23 @@ struct agp_bridge_driver uninorth_agp_driver = {
.create_gatt_table = uninorth_create_gatt_table,
.free_gatt_table = uninorth_free_gatt_table,
.insert_memory = uninorth_insert_memory,
- .remove_memory = agp_generic_remove_memory,
+ .remove_memory = uninorth_remove_memory,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
- .cant_use_aperture = 1,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
+ .cant_use_aperture = true,
+ .needs_scratch_page = true,
};
-struct agp_bridge_driver u3_agp_driver = {
+const struct agp_bridge_driver u3_agp_driver = {
.owner = THIS_MODULE,
.aperture_sizes = (void *)u3_sizes,
.size_type = U32_APER_SIZE,
- .num_aperture_sizes = 8,
+ .num_aperture_sizes = ARRAY_SIZE(u3_sizes),
.configure = uninorth_configure,
.fetch_size = uninorth_fetch_size,
.cleanup = uninorth_cleanup,
@@ -518,17 +544,20 @@ struct agp_bridge_driver u3_agp_driver = {
.agp_enable = uninorth_agp_enable,
.create_gatt_table = uninorth_create_gatt_table,
.free_gatt_table = uninorth_free_gatt_table,
- .insert_memory = u3_insert_memory,
- .remove_memory = u3_remove_memory,
+ .insert_memory = uninorth_insert_memory,
+ .remove_memory = uninorth_remove_memory,
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
- .cant_use_aperture = 1,
- .needs_scratch_page = 1,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
+ .cant_use_aperture = true,
+ .needs_scratch_page = true,
};
-static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
+static struct agp_device_ids uninorth_agp_device_ids[] = {
{
.device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
.chipset_name = "UniNorth",
@@ -563,8 +592,8 @@ static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
},
};
-static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_uninorth_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct agp_device_ids *devs = uninorth_agp_device_ids;
struct agp_bridge_data *bridge;
@@ -579,14 +608,14 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
/* probe for known chipsets */
for (j = 0; devs[j].chipset_name != NULL; ++j) {
if (pdev->device == devs[j].device_id) {
- printk(KERN_INFO PFX "Detected Apple %s chipset\n",
- devs[j].chipset_name);
+ dev_info(&pdev->dev, "Apple %s chipset\n",
+ devs[j].chipset_name);
goto found;
}
}
- printk(KERN_ERR PFX "Unsupported Apple chipset (device id: %04x).\n",
- pdev->device);
+ dev_err(&pdev->dev, "unsupported Apple chipset [%04x/%04x]\n",
+ pdev->vendor, pdev->device);
return -ENODEV;
found:
@@ -601,8 +630,8 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
uninorth_node = of_find_node_by_name(NULL, "u3");
}
if (uninorth_node) {
- int *revprop = (int *)
- get_property(uninorth_node, "device-rev", NULL);
+ const int *revprop = of_get_property(uninorth_node,
+ "device-rev", NULL);
if (revprop != NULL)
uninorth_rev = *revprop & 0x3f;
of_node_put(uninorth_node);
@@ -634,7 +663,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_uninorth_remove(struct pci_dev *pdev)
+static void agp_uninorth_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -683,5 +712,11 @@ static void __exit agp_uninorth_cleanup(void)
module_init(agp_uninorth_init);
module_exit(agp_uninorth_cleanup);
+module_param(aperture, charp, 0);
+MODULE_PARM_DESC(aperture,
+ "Aperture size, must be power of two between 4MB and an\n"
+ "\t\tupper limit specific to the UniNorth revision.\n"
+ "\t\tDefault: " DEFAULT_APERTURE_STRING "M");
+
MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 97b0a890ba7..228f20cddc0 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -9,7 +9,7 @@
#include <linux/agp_backend.h>
#include "agp.h"
-static struct pci_device_id agp_via_pci_table[];
+static const struct pci_device_id agp_via_pci_table[];
#define VIA_GARTCTRL 0x80
#define VIA_APSIZE 0x84
@@ -43,16 +43,15 @@ static int via_fetch_size(void)
static int via_configure(void)
{
- u32 temp;
struct aper_size_info_8 *current_size;
current_size = A_SIZE_8(agp_bridge->current_size);
/* aperture size */
pci_write_config_byte(agp_bridge->dev, VIA_APSIZE,
current_size->size_value);
- /* address to map too */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ /* address to map to */
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* GART control register */
pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000000f);
@@ -89,7 +88,7 @@ static void via_tlbflush(struct agp_memory *mem)
}
-static struct aper_size_info_8 via_generic_sizes[9] =
+static const struct aper_size_info_8 via_generic_sizes[9] =
{
{256, 65536, 6, 0},
{128, 32768, 5, 128},
@@ -132,9 +131,9 @@ static int via_configure_agp3(void)
current_size = A_SIZE_16(agp_bridge->current_size);
- /* address to map too */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ /* address to map to */
+ agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
+ AGP_APERTURE_BAR);
/* attbase - aperture GATT base */
pci_write_config_dword(agp_bridge->dev, VIA_AGP3_ATTBASE,
@@ -170,11 +169,12 @@ static void via_tlbflush_agp3(struct agp_memory *mem)
}
-static struct agp_bridge_driver via_agp3_driver = {
+static const struct agp_bridge_driver via_agp3_driver = {
.owner = THIS_MODULE,
.aperture_sizes = agp3_generic_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 10,
+ .needs_scratch_page = true,
.configure = via_configure_agp3,
.fetch_size = via_fetch_size_agp3,
.cleanup = via_cleanup_agp3,
@@ -190,14 +190,18 @@ static struct agp_bridge_driver via_agp3_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_bridge_driver via_driver = {
+static const struct agp_bridge_driver via_driver = {
.owner = THIS_MODULE,
.aperture_sizes = via_generic_sizes,
.size_type = U8_APER_SIZE,
.num_aperture_sizes = 9,
+ .needs_scratch_page = true,
.configure = via_configure,
.fetch_size = via_fetch_size,
.cleanup = via_cleanup,
@@ -213,10 +217,13 @@ static struct agp_bridge_driver via_driver = {
.alloc_by_type = agp_generic_alloc_by_type,
.free_by_type = agp_generic_free_by_type,
.agp_alloc_page = agp_generic_alloc_page,
+ .agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
+ .agp_destroy_pages = agp_generic_destroy_pages,
+ .agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static struct agp_device_ids via_agp_device_ids[] __devinitdata =
+static struct agp_device_ids via_agp_device_ids[] =
{
{
.device_id = PCI_DEVICE_ID_VIA_82C597_0,
@@ -345,6 +352,12 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
.chipset_name = "PT880",
},
+ /* PT880 Ultra */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_PT880ULTRA,
+ .chipset_name = "PT880 Ultra",
+ },
+
/* PT890 */
{
.device_id = PCI_DEVICE_ID_VIA_8783_0,
@@ -374,9 +387,37 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata =
/* P4M800CE */
{
.device_id = PCI_DEVICE_ID_VIA_P4M800CE,
- .chipset_name = "P4M800CE",
+ .chipset_name = "VT3314",
+ },
+ /* VT3324 / CX700 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_VT3324,
+ .chipset_name = "CX700",
+ },
+ /* VT3336 - this is a chipset for AMD Athlon/K8 CPU. Due to K8's unique
+ * architecture, the AGP resource and behavior are different from
+ * the traditional AGP which resides only in chipset. AGP is used
+ * by 3D driver which wasn't available for the VT3336 and VT3364
+ * generation until now. Unfortunately, by testing, VT3364 works
+ * but VT3336 doesn't. - explanation from via, just leave this as
+ * as a placeholder to avoid future patches adding it back in.
+ */
+#if 0
+ {
+ .device_id = PCI_DEVICE_ID_VIA_VT3336,
+ .chipset_name = "VT3336",
+ },
+#endif
+ /* P4M890 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_P4M890,
+ .chipset_name = "P4M890",
+ },
+ /* P4M900 */
+ {
+ .device_id = PCI_DEVICE_ID_VIA_VT3364,
+ .chipset_name = "P4M900",
},
-
{ }, /* dummy final entry, always present */
};
@@ -396,8 +437,7 @@ static void check_via_agp3 (struct agp_bridge_data *bridge)
}
-static int __devinit agp_via_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int agp_via_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct agp_device_ids *devs = via_agp_device_ids;
struct agp_bridge_data *bridge;
@@ -443,7 +483,7 @@ static int __devinit agp_via_probe(struct pci_dev *pdev,
return agp_add_bridge(bridge);
}
-static void __devexit agp_via_remove(struct pci_dev *pdev)
+static void agp_via_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
@@ -479,7 +519,7 @@ static int agp_via_resume(struct pci_dev *pdev)
#endif /* CONFIG_PM */
/* must be the same order as name table above */
-static struct pci_device_id agp_via_pci_table[] = {
+static const struct pci_device_id agp_via_pci_table[] = {
#define ID(x) \
{ \
.class = (PCI_CLASS_BRIDGE_HOST << 8), \
@@ -511,12 +551,16 @@ static struct pci_device_id agp_via_pci_table[] = {
ID(PCI_DEVICE_ID_VIA_8763_0),
ID(PCI_DEVICE_ID_VIA_8378_0),
ID(PCI_DEVICE_ID_VIA_PT880),
+ ID(PCI_DEVICE_ID_VIA_PT880ULTRA),
ID(PCI_DEVICE_ID_VIA_8783_0),
ID(PCI_DEVICE_ID_VIA_PX8X0_0),
ID(PCI_DEVICE_ID_VIA_3269_0),
ID(PCI_DEVICE_ID_VIA_83_87XX_1),
ID(PCI_DEVICE_ID_VIA_3296_0),
ID(PCI_DEVICE_ID_VIA_P4M800CE),
+ ID(PCI_DEVICE_ID_VIA_VT3324),
+ ID(PCI_DEVICE_ID_VIA_P4M890),
+ ID(PCI_DEVICE_ID_VIA_VT3364),
{ }
};
@@ -551,4 +595,4 @@ module_init(agp_via_init);
module_exit(agp_via_cleanup);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
+MODULE_AUTHOR("Dave Jones <davej@redhat.com>");