X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fagp%2Fsworks-agp.c;h=4f2d7d99902f1cfc21ad988846d1176609b3ccf2;hb=refs%2Fheads%2Fvserver;hp=44b24fa6f2a57ba4d7137a1f1638b326bd61f1fc;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 44b24fa6f..4f2d7d999 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include #include "agp.h" @@ -51,7 +54,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map) } SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); - page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), + 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)); @@ -61,7 +64,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map) } global_cache_flush(); - 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); return 0; @@ -81,7 +84,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) { @@ -100,19 +103,17 @@ static int serverworks_create_gatt_pages(int nr_tables) int retval = 0; int i; - tables = kmalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), + tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *), GFP_KERNEL); - if (tables == NULL) { + if (tables == NULL) return -ENOMEM; - } - memset(tables, 0, sizeof(struct serverworks_page_map *) * (nr_tables + 1)); + for (i = 0; i < nr_tables; i++) { - entry = kmalloc(sizeof(struct serverworks_page_map), GFP_KERNEL); + entry = kzalloc(sizeof(struct serverworks_page_map), GFP_KERNEL); if (entry == NULL) { retval = -ENOMEM; break; } - memset(entry, 0, sizeof(struct serverworks_page_map)); tables[i] = entry; retval = serverworks_create_page_map(entry); if (retval != 0) break; @@ -141,7 +142,7 @@ static int serverworks_create_gatt_pages(int nr_tables) #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) #endif -static int serverworks_create_gatt_table(void) +static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) { struct aper_size_info_lvl2 *value; struct serverworks_page_map page_dir; @@ -160,9 +161,9 @@ static int serverworks_create_gatt_table(void) 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_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); + writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); } retval = serverworks_create_gatt_pages(value->num_entries / 1024); @@ -174,7 +175,7 @@ static int serverworks_create_gatt_table(void) 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_phys(page_dir.real); + agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); /* Get the address for the gart region. * This is a bus address even on the alpha, b/c its @@ -184,18 +185,17 @@ static int serverworks_create_gatt_table(void) 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_phys(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_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); return 0; } -static int serverworks_free_gatt_table(void) +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; @@ -242,13 +242,27 @@ static int serverworks_fetch_size(void) */ static void serverworks_tlbflush(struct agp_memory *temp) { + unsigned long timeout; + writeb(1, serverworks_private.registers+SVWRKS_POSTFLUSH); - while (readb(serverworks_private.registers+SVWRKS_POSTFLUSH) == 1) + timeout = jiffies + 3*HZ; + 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"); + break; + } + } writel(1, serverworks_private.registers+SVWRKS_DIRFLUSH); - while(readl(serverworks_private.registers+SVWRKS_DIRFLUSH) == 1) + timeout = jiffies + 3*HZ; + 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"); + break; + } + } } static int serverworks_configure(void) @@ -341,7 +355,7 @@ static int serverworks_insert_memory(struct agp_memory *mem, 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(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); + writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr)); } serverworks_tlbflush(mem); return 0; @@ -387,15 +401,15 @@ static struct aper_size_info_lvl2 serverworks_sizes[7] = {32, 8192, 0xfe000000} }; -static void serverworks_agp_enable(u32 mode) +static void serverworks_agp_enable(struct agp_bridge_data *bridge, u32 mode) { u32 command; pci_read_config_dword(serverworks_private.svrwrks_dev, - agp_bridge->capndx + PCI_AGP_STATUS, + bridge->capndx + PCI_AGP_STATUS, &command); - command = agp_collect_device_status(mode, command); + command = agp_collect_device_status(bridge, mode, command); command &= ~0x10; /* disable FW */ command &= ~0x08; @@ -403,13 +417,13 @@ static void serverworks_agp_enable(u32 mode) command |= 0x100; pci_write_config_dword(serverworks_private.svrwrks_dev, - agp_bridge->capndx + PCI_AGP_COMMAND, + bridge->capndx + PCI_AGP_COMMAND, command); agp_device_command(command, 0); } -struct agp_bridge_driver sworks_driver = { +static struct agp_bridge_driver sworks_driver = { .owner = THIS_MODULE, .aperture_sizes = serverworks_sizes, .size_type = LVL2_APER_SIZE, @@ -453,9 +467,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, switch (pdev->device) { case 0x0006: - /* ServerWorks CNB20HE - Fail silently.*/ - printk (KERN_ERR PFX "Detected ServerWorks CNB20HE chipset: No AGP present.\n"); + printk (KERN_ERR PFX "ServerWorks CNB20HE is unsupported due to lack of documentation.\n"); return -ENODEV; case PCI_DEVICE_ID_SERVERWORKS_HE: @@ -541,7 +553,7 @@ static int __init agp_serverworks_init(void) { if (agp_off) return -EINVAL; - return pci_module_init(&agp_serverworks_pci_driver); + return pci_register_driver(&agp_serverworks_pci_driver); } static void __exit agp_serverworks_cleanup(void)