mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 18:13:04 +00:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
* master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart: [AGPGART] drivers/char/agp/sgi-agp.c: check kmalloc() return value [AGPGART] Fix PCI-posting flush typo. [AGPGART] fix detection of aperture size versus GTT size on G965 [AGPGART] Remove unnecessary flushes when inserting and removing pages. [AGPGART] K8M890 support for amd-k8.
This commit is contained in:
commit
a7ec3f5289
@ -225,6 +225,10 @@ struct agp_bridge_data {
|
||||
#define I810_GMS_DISABLE 0x00000000
|
||||
#define I810_PGETBL_CTL 0x2020
|
||||
#define I810_PGETBL_ENABLED 0x00000001
|
||||
#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 I810_DRAM_CTL 0x3000
|
||||
#define I810_DRAM_ROW_0 0x00000001
|
||||
#define I810_DRAM_ROW_0_SDRAM 0x00000001
|
||||
|
@ -650,6 +650,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_K8M890CE,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},
|
||||
/* VIA K8T890 */
|
||||
{
|
||||
.class = (PCI_CLASS_BRIDGE_HOST << 8),
|
||||
|
@ -965,6 +965,9 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
|
||||
if (!bridge)
|
||||
return -EINVAL;
|
||||
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
temp = bridge->current_size;
|
||||
|
||||
switch (bridge->driver->size_type) {
|
||||
@ -1016,8 +1019,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
|
||||
|
||||
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. */
|
||||
}
|
||||
readl(bridge->gatt_table+j-1); /* PCI Posting. */
|
||||
|
||||
bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
@ -1034,6 +1037,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
|
||||
if (!bridge)
|
||||
return -EINVAL;
|
||||
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
if (type != 0 || mem->type != 0) {
|
||||
/* The generic routines know nothing of memory types */
|
||||
return -EINVAL;
|
||||
@ -1042,10 +1048,9 @@ 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;
|
||||
}
|
||||
|
@ -207,6 +207,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
|
||||
int i, j, num_entries;
|
||||
void *temp;
|
||||
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
temp = agp_bridge->current_size;
|
||||
num_entries = A_SIZE_FIX(temp)->num_entries;
|
||||
|
||||
@ -221,12 +224,16 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
|
||||
if (type != 0 || mem->type != 0) {
|
||||
if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
|
||||
/* special insert */
|
||||
global_cache_flush();
|
||||
if (!mem->is_flushed) {
|
||||
global_cache_flush();
|
||||
mem->is_flushed = TRUE;
|
||||
}
|
||||
|
||||
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();
|
||||
readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
|
||||
|
||||
agp_bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
}
|
||||
@ -236,14 +243,17 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
|
||||
}
|
||||
|
||||
insert:
|
||||
global_cache_flush();
|
||||
if (!mem->is_flushed) {
|
||||
global_cache_flush();
|
||||
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),
|
||||
intel_i810_private.registers+I810_PTE_BASE+(j*4));
|
||||
readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
|
||||
}
|
||||
global_cache_flush();
|
||||
readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */
|
||||
|
||||
agp_bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
@ -254,12 +264,14 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
|
||||
{
|
||||
int i;
|
||||
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
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. */
|
||||
}
|
||||
readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
|
||||
|
||||
global_cache_flush();
|
||||
agp_bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
}
|
||||
@ -370,6 +382,11 @@ static struct _intel_i830_private {
|
||||
struct pci_dev *i830_dev; /* device one */
|
||||
volatile u8 __iomem *registers;
|
||||
volatile u32 __iomem *gtt; /* I915G */
|
||||
/* gtt_entries is the number of gtt entries that are already mapped
|
||||
* to stolen memory. Stolen memory is larger than the memory mapped
|
||||
* through gtt_entries, as it includes some reserved space for the BIOS
|
||||
* popup and for the GTT.
|
||||
*/
|
||||
int gtt_entries;
|
||||
} intel_i830_private;
|
||||
|
||||
@ -380,14 +397,41 @@ static void intel_i830_init_gtt_entries(void)
|
||||
u8 rdct;
|
||||
int local = 0;
|
||||
static const int ddt[4] = { 0, 16, 32, 64 };
|
||||
int size;
|
||||
int size; /* reserved space (in kb) at the top of stolen memory */
|
||||
|
||||
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 (IS_I965) {
|
||||
u32 pgetbl_ctl;
|
||||
|
||||
pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL,
|
||||
&pgetbl_ctl);
|
||||
/* The 965 has a field telling us the size of the GTT,
|
||||
* which may be larger than what is necessary to map the
|
||||
* aperture.
|
||||
*/
|
||||
switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) {
|
||||
case I965_PGETBL_SIZE_128KB:
|
||||
size = 128;
|
||||
break;
|
||||
case I965_PGETBL_SIZE_256KB:
|
||||
size = 256;
|
||||
break;
|
||||
case I965_PGETBL_SIZE_512KB:
|
||||
size = 512;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_INFO PFX "Unknown page table size, "
|
||||
"assuming 512KB\n");
|
||||
size = 512;
|
||||
}
|
||||
size += 4; /* add in BIOS popup space */
|
||||
} else {
|
||||
/* On previous hardware, the GTT size was just what was
|
||||
* required to map the aperture.
|
||||
*/
|
||||
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) {
|
||||
@ -576,6 +620,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
|
||||
int i,j,num_entries;
|
||||
void *temp;
|
||||
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
temp = agp_bridge->current_size;
|
||||
num_entries = A_SIZE_FIX(temp)->num_entries;
|
||||
|
||||
@ -598,16 +645,18 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
|
||||
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
|
||||
return -EINVAL;
|
||||
|
||||
global_cache_flush(); /* FIXME: Necessary ?*/
|
||||
if (!mem->is_flushed) {
|
||||
global_cache_flush();
|
||||
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),
|
||||
intel_i830_private.registers+I810_PTE_BASE+(j*4));
|
||||
readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
|
||||
}
|
||||
readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
|
||||
|
||||
global_cache_flush();
|
||||
agp_bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
}
|
||||
@ -617,7 +666,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
|
||||
{
|
||||
int i;
|
||||
|
||||
global_cache_flush();
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
if (pg_start < intel_i830_private.gtt_entries) {
|
||||
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
|
||||
@ -626,10 +676,9 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
|
||||
|
||||
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. */
|
||||
}
|
||||
readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
|
||||
|
||||
global_cache_flush();
|
||||
agp_bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
}
|
||||
@ -686,6 +735,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
|
||||
int i,j,num_entries;
|
||||
void *temp;
|
||||
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
temp = agp_bridge->current_size;
|
||||
num_entries = A_SIZE_FIX(temp)->num_entries;
|
||||
|
||||
@ -708,15 +760,17 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
|
||||
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
|
||||
return -EINVAL;
|
||||
|
||||
global_cache_flush();
|
||||
if (!mem->is_flushed) {
|
||||
global_cache_flush();
|
||||
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), intel_i830_private.gtt+j);
|
||||
readl(intel_i830_private.gtt+j); /* PCI Posting. */
|
||||
}
|
||||
readl(intel_i830_private.gtt+j-1);
|
||||
|
||||
global_cache_flush();
|
||||
agp_bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
}
|
||||
@ -726,7 +780,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
|
||||
{
|
||||
int i;
|
||||
|
||||
global_cache_flush();
|
||||
if (mem->page_count == 0)
|
||||
return 0;
|
||||
|
||||
if (pg_start < intel_i830_private.gtt_entries) {
|
||||
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
|
||||
@ -735,30 +790,34 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
|
||||
|
||||
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);
|
||||
}
|
||||
readl(intel_i830_private.gtt+i-1);
|
||||
|
||||
global_cache_flush();
|
||||
agp_bridge->driver->tlb_flush(mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_i915_fetch_size(void)
|
||||
/* Return the aperture size by just checking the resource length. The effect
|
||||
* described in the spec of the MSAC registers is just changing of the
|
||||
* resource size.
|
||||
*/
|
||||
static int intel_i9xx_fetch_size(void)
|
||||
{
|
||||
struct aper_size_info_fixed *values;
|
||||
u32 temp, offset;
|
||||
int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes);
|
||||
int aper_size; /* size in megabytes */
|
||||
int i;
|
||||
|
||||
#define I915_256MB_ADDRESS_MASK (1<<27)
|
||||
aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
|
||||
|
||||
values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
|
||||
for (i = 0; i < num_sizes; i++) {
|
||||
if (aper_size == intel_i830_sizes[i].size) {
|
||||
agp_bridge->current_size = intel_i830_sizes + i;
|
||||
agp_bridge->previous_size = agp_bridge->current_size;
|
||||
return aper_size;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The intel i915 automatically initializes the agp aperture during POST.
|
||||
@ -821,40 +880,9 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
|
||||
return addr | bridge->driver->masks[type].mask;
|
||||
}
|
||||
|
||||
static int intel_i965_fetch_size(void)
|
||||
{
|
||||
struct aper_size_info_fixed *values;
|
||||
u32 offset = 0;
|
||||
u8 temp;
|
||||
|
||||
#define I965_512MB_ADDRESS_MASK (3<<1)
|
||||
|
||||
values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
|
||||
|
||||
pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp);
|
||||
temp &= I965_512MB_ADDRESS_MASK;
|
||||
switch (temp) {
|
||||
case 0x00:
|
||||
offset = 0; /* 128MB */
|
||||
break;
|
||||
case 0x06:
|
||||
offset = 3; /* 512MB */
|
||||
break;
|
||||
default:
|
||||
case 0x02:
|
||||
offset = 2; /* 256MB */
|
||||
break;
|
||||
}
|
||||
|
||||
agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);
|
||||
|
||||
/* The i965 GTT is always sized as if it had a 512kB aperture size */
|
||||
return 512;
|
||||
}
|
||||
|
||||
/* The intel i965 automatically initializes the agp aperture during POST.
|
||||
+ * Use the memory already set aside for in the GTT.
|
||||
+ */
|
||||
* Use the memory already set aside for in the GTT.
|
||||
*/
|
||||
static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
|
||||
{
|
||||
int page_order;
|
||||
@ -1574,7 +1602,7 @@ static struct agp_bridge_driver intel_915_driver = {
|
||||
.num_aperture_sizes = 4,
|
||||
.needs_scratch_page = TRUE,
|
||||
.configure = intel_i915_configure,
|
||||
.fetch_size = intel_i915_fetch_size,
|
||||
.fetch_size = intel_i9xx_fetch_size,
|
||||
.cleanup = intel_i915_cleanup,
|
||||
.tlb_flush = intel_i810_tlbflush,
|
||||
.mask_memory = intel_i810_mask_memory,
|
||||
@ -1598,7 +1626,7 @@ static struct agp_bridge_driver intel_i965_driver = {
|
||||
.num_aperture_sizes = 4,
|
||||
.needs_scratch_page = TRUE,
|
||||
.configure = intel_i915_configure,
|
||||
.fetch_size = intel_i965_fetch_size,
|
||||
.fetch_size = intel_i9xx_fetch_size,
|
||||
.cleanup = intel_i915_cleanup,
|
||||
.tlb_flush = intel_i810_tlbflush,
|
||||
.mask_memory = intel_i965_mask_memory,
|
||||
|
@ -281,10 +281,11 @@ 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) {
|
||||
|
@ -1277,6 +1277,7 @@
|
||||
#define PCI_DEVICE_ID_VIA_3296_0 0x0296
|
||||
#define PCI_DEVICE_ID_VIA_8363_0 0x0305
|
||||
#define PCI_DEVICE_ID_VIA_P4M800CE 0x0314
|
||||
#define PCI_DEVICE_ID_VIA_K8M890CE 0x0336
|
||||
#define PCI_DEVICE_ID_VIA_8371_0 0x0391
|
||||
#define PCI_DEVICE_ID_VIA_8501_0 0x0501
|
||||
#define PCI_DEVICE_ID_VIA_82C561 0x0561
|
||||
|
Loading…
Reference in New Issue
Block a user