diff options
Diffstat (limited to 'drivers/char')
39 files changed, 569 insertions, 205 deletions
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 178e2e9e9f0..d6f36c004d9 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -107,7 +107,7 @@ struct agp_bridge_driver { 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 *, struct page *, 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 *); @@ -121,6 +121,11 @@ struct agp_bridge_driver { void (*agp_destroy_pages)(struct agp_memory *); int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); void (*chipset_flush)(struct agp_bridge_data *); + + int (*agp_map_page)(struct page *page, dma_addr_t *ret); + void (*agp_unmap_page)(struct page *page, dma_addr_t dma); + int (*agp_map_memory)(struct agp_memory *mem); + void (*agp_unmap_memory)(struct agp_memory *mem); }; struct agp_bridge_data { @@ -134,7 +139,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; @@ -291,7 +297,7 @@ 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, - struct page *page, 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); @@ -312,9 +318,6 @@ void agp3_generic_cleanup(void); #define AGP_GENERIC_SIZES_ENTRIES 11 extern const 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 int agp_off; extern int agp_try_unsupported_boot; diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 201ef3ffd48..d2ce68f27e4 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -152,7 +152,7 @@ static struct page *m1541_alloc_page(struct agp_bridge_data *bridge) 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) | - phys_to_gart(page_to_phys(page))) | ALI_CACHE_FLUSH_EN )); + page_to_phys(page)) | ALI_CACHE_FLUSH_EN )); return page; } @@ -180,7 +180,7 @@ static void m1541_destroy_page(struct page *page, int flags) 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) | - phys_to_gart(page_to_phys(page))) | ALI_CACHE_FLUSH_EN)); + page_to_phys(page)) | ALI_CACHE_FLUSH_EN)); } agp_generic_destroy_page(page, flags); } diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index ba9bde71eaa..73dbf40c874 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -44,7 +44,7 @@ static int amd_create_page_map(struct amd_page_map *page_map) #ifndef CONFIG_X86 SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); - page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), + page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { ClearPageReserved(virt_to_page(page_map->real)); @@ -160,7 +160,7 @@ 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 @@ -173,7 +173,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge) /* 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. */ } @@ -325,7 +325,9 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); writel(agp_generic_mask_memory(agp_bridge, - mem->pages[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); diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 3bf5dda90f4..2fb2e6cc322 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -79,7 +79,8 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { tmp = agp_bridge->driver->mask_memory(agp_bridge, - mem->pages[i], mask_type); + page_to_phys(mem->pages[i]), + mask_type); BUG_ON(tmp & 0xffffff0000000ffcULL); pte = (tmp & 0x000000ff00000000ULL) >> 28; @@ -177,7 +178,7 @@ static const struct aper_size_info_32 amd_8151_sizes[7] = static int amd_8151_configure(void) { - unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); + unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); int i; /* Configure AGP regs in each x86-64 host bridge. */ @@ -557,7 +558,7 @@ static void __devexit 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); diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 33656e144cc..3b2ecbe86eb 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -302,7 +302,8 @@ static int ati_insert_memory(struct agp_memory * mem, addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); writel(agp_bridge->driver->mask_memory(agp_bridge, - mem->pages[i], mem->type), + page_to_phys(mem->pages[i]), + mem->type), cur_gatt+GET_GATT_OFF(addr)); } readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */ @@ -359,7 +360,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); @@ -389,7 +390,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) /* 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, + 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. */ } diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index cfa5a649dfe..ad87753f6de 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -149,9 +149,21 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) return -ENOMEM; } - bridge->scratch_page_real = phys_to_gart(page_to_phys(page)); - bridge->scratch_page = - bridge->driver->mask_memory(bridge, page, 0); + bridge->scratch_page_page = page; + if (bridge->driver->agp_map_page) { + if (bridge->driver->agp_map_page(page, + &bridge->scratch_page_dma)) { + dev_err(&bridge->dev->dev, + "unable to dma-map scratch page\n"); + rc = -ENOMEM; + goto err_out_nounmap; + } + } else { + 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(); @@ -191,8 +203,14 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) return 0; err_out: + if (bridge->driver->needs_scratch_page && + bridge->driver->agp_unmap_page) { + bridge->driver->agp_unmap_page(bridge->scratch_page_page, + bridge->scratch_page_dma); + } +err_out_nounmap: if (bridge->driver->needs_scratch_page) { - void *va = gart_to_virt(bridge->scratch_page_real); + void *va = page_address(bridge->scratch_page_page); bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); @@ -219,7 +237,11 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) if (bridge->driver->agp_destroy_page && bridge->driver->needs_scratch_page) { - void *va = gart_to_virt(bridge->scratch_page_real); + void *va = page_address(bridge->scratch_page_page); + + if (bridge->driver->agp_unmap_page) + bridge->driver->agp_unmap_page(bridge->scratch_page_page, + bridge->scratch_page_dma); bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index 35d50f2861b..793f39ea961 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c @@ -67,7 +67,7 @@ static const struct gatt_mask efficeon_generic_masks[] = /* 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 = phys_to_gart(page_to_phys(page)); + unsigned long addr = page_to_phys(page); return addr | 0x00000001; } @@ -226,7 +226,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge) 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); diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 1e8b461b91f..c50543966eb 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -437,6 +437,12 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) curr->bridge->driver->cache_flush(); curr->is_flushed = true; } + + if (curr->bridge->driver->agp_map_memory) { + ret_val = curr->bridge->driver->agp_map_memory(curr); + if (ret_val) + return ret_val; + } ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type); if (ret_val != 0) @@ -478,6 +484,9 @@ int agp_unbind_memory(struct agp_memory *curr) if (ret_val != 0) return ret_val; + if (curr->bridge->driver->agp_unmap_memory) + curr->bridge->driver->agp_unmap_memory(curr); + curr->is_bound = false; curr->pg_start = 0; spin_lock(&curr->bridge->mapped_lock); @@ -979,7 +988,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) set_memory_uc((unsigned long)table, 1 << page_order); bridge->gatt_table = (void *)table; #else - bridge->gatt_table = ioremap_nocache(virt_to_gart(table), + bridge->gatt_table = ioremap_nocache(virt_to_phys(table), (PAGE_SIZE * (1 << page_order))); bridge->driver->cache_flush(); #endif @@ -992,7 +1001,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++) { @@ -1132,7 +1141,9 @@ 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->pages[i], mask_type), + 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. */ @@ -1347,9 +1358,8 @@ void global_cache_flush(void) EXPORT_SYMBOL(global_cache_flush); unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge, - struct page *page, int type) + dma_addr_t addr, int type) { - unsigned long addr = phys_to_gart(page_to_phys(page)); /* memory type is ignored in the generic routine */ if (bridge->driver->masks) return addr | bridge->driver->masks[0].mask; diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 8f3d4c18491..501e293e5ad 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -107,7 +107,7 @@ 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) { @@ -246,7 +246,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); @@ -394,10 +394,8 @@ 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, - struct page *page, int type) +hp_zx1_mask_memory (struct agp_bridge_data *bridge, dma_addr_t addr, int type) { - unsigned long addr = phys_to_gart(page_to_phys(page)); return HP_ZX1_PDIR_VALID_BIT | addr; } diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 60cc35bb5db..e763d3312ce 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -61,7 +61,7 @@ #define WR_FLUSH_GATT(index) RD_GATT(index) static unsigned long i460_mask_memory (struct agp_bridge_data *bridge, - unsigned long addr, int type); + dma_addr_t addr, int type); static struct { void *gatt; /* ioremap'd GATT area */ @@ -325,7 +325,7 @@ 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 = phys_to_gart(page_to_phys(mem->pages[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, i460_mask_memory(agp_bridge, paddr, mem->type)); } @@ -382,7 +382,7 @@ static int i460_alloc_large_page (struct lp_desc *lp) return -ENOMEM; } - lp->paddr = phys_to_gart(page_to_phys(lp->page)); + lp->paddr = page_to_phys(lp->page); lp->refcount = 0; atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); return 0; @@ -546,20 +546,13 @@ static void i460_destroy_page (struct page *page, int 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); } -static unsigned long i460_page_mask_memory(struct agp_bridge_data *bridge, - struct page *page, int type) -{ - unsigned long addr = phys_to_gart(page_to_phys(page)); - return i460_mask_memory(bridge, addr, type); -} - const struct agp_bridge_driver intel_i460_driver = { .owner = THIS_MODULE, .aperture_sizes = i460_sizes, @@ -569,7 +562,7 @@ const struct agp_bridge_driver intel_i460_driver = { .fetch_size = i460_fetch_size, .cleanup = i460_cleanup, .tlb_flush = i460_tlb_flush, - .mask_memory = i460_page_mask_memory, + .mask_memory = i460_mask_memory, .masks = i460_masks, .agp_enable = agp_generic_enable, .cache_flush = global_cache_flush, diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index c5855779058..1540e693d91 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -10,6 +10,16 @@ #include <linux/agp_backend.h> #include "agp.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_DMAR). + * Only newer chipsets need to bother with this, of course. + */ +#ifdef CONFIG_DMAR +#define USE_PCI_DMA_API 1 +#endif + #define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588 #define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a #define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970 @@ -172,6 +182,123 @@ static struct _intel_private { int resource_valid; } intel_private; +#ifdef USE_PCI_DMA_API +static int intel_agp_map_page(struct page *page, dma_addr_t *ret) +{ + *ret = pci_map_page(intel_private.pcidev, page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(intel_private.pcidev, *ret)) + return -EINVAL; + return 0; +} + +static void intel_agp_unmap_page(struct page *page, dma_addr_t dma) +{ + pci_unmap_page(intel_private.pcidev, dma, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +} + +static void intel_agp_free_sglist(struct agp_memory *mem) +{ + struct sg_table st; + + st.sgl = mem->sg_list; + st.orig_nents = st.nents = mem->page_count; + + sg_free_table(&st); + + mem->sg_list = NULL; + mem->num_sg = 0; +} + +static int intel_agp_map_memory(struct agp_memory *mem) +{ + struct sg_table st; + struct scatterlist *sg; + int i; + + DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); + + if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) + return -ENOMEM; + + mem->sg_list = sg = st.sgl; + + for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg)) + sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0); + + mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, + mem->page_count, PCI_DMA_BIDIRECTIONAL); + if (unlikely(!mem->num_sg)) { + intel_agp_free_sglist(mem); + return -ENOMEM; + } + return 0; +} + +static void intel_agp_unmap_memory(struct agp_memory *mem) +{ + DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); + + pci_unmap_sg(intel_private.pcidev, mem->sg_list, + mem->page_count, PCI_DMA_BIDIRECTIONAL); + intel_agp_free_sglist(mem); +} + +static void intel_agp_insert_sg_entries(struct agp_memory *mem, + off_t pg_start, int mask_type) +{ + struct scatterlist *sg; + int i, j; + + j = pg_start; + + WARN_ON(!mem->num_sg); + + if (mem->num_sg == mem->page_count) { + for_each_sg(mem->sg_list, sg, mem->page_count, i) { + writel(agp_bridge->driver->mask_memory(agp_bridge, + sg_dma_address(sg), mask_type), + intel_private.gtt+j); + j++; + } + } else { + /* sg may merge pages, but we have to seperate + * per-page addr for GTT */ + unsigned int len, m; + + for_each_sg(mem->sg_list, sg, mem->num_sg, i) { + len = sg_dma_len(sg) / PAGE_SIZE; + for (m = 0; m < len; m++) { + writel(agp_bridge->driver->mask_memory(agp_bridge, + sg_dma_address(sg) + m * PAGE_SIZE, + mask_type), + intel_private.gtt+j); + j++; + } + } + } + readl(intel_private.gtt+j-1); +} + +#else + +static void intel_agp_insert_sg_entries(struct agp_memory *mem, + off_t pg_start, int mask_type) +{ + int i, j; + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + writel(agp_bridge->driver->mask_memory(agp_bridge, + page_to_phys(mem->pages[i]), mask_type), + intel_private.gtt+j); + } + + readl(intel_private.gtt+j-1); +} + +#endif + static int intel_i810_fetch_size(void) { u32 smram_miscc; @@ -345,8 +472,7 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, global_cache_flush(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { writel(agp_bridge->driver->mask_memory(agp_bridge, - mem->pages[i], - mask_type), + page_to_phys(mem->pages[i]), mask_type), intel_private.registers+I810_PTE_BASE+(j*4)); } readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); @@ -463,9 +589,8 @@ static void intel_i810_free_by_type(struct agp_memory *curr) } static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, - struct page *page, int type) + dma_addr_t addr, int type) { - unsigned long addr = phys_to_gart(page_to_phys(page)); /* Type checking must be done elsewhere */ return addr | bridge->driver->masks[type].mask; } @@ -853,7 +978,7 @@ static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start, for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { writel(agp_bridge->driver->mask_memory(agp_bridge, - mem->pages[i], mask_type), + page_to_phys(mem->pages[i]), mask_type), intel_private.registers+I810_PTE_BASE+(j*4)); } readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); @@ -1017,6 +1142,12 @@ static int intel_i915_configure(void) intel_i9xx_setup_flush(); +#ifdef USE_PCI_DMA_API + if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) + dev_err(&intel_private.pcidev->dev, + "set gfx device dma mask 36bit failed!\n"); +#endif + return 0; } @@ -1041,7 +1172,7 @@ static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, int type) { - int i, j, num_entries; + int num_entries; void *temp; int ret = -EINVAL; int mask_type; @@ -1065,7 +1196,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, if ((pg_start + mem->page_count) > num_entries) goto out_err; - /* The i915 can't check the GTT for entries since its read only, + /* The i915 can't check the GTT for entries since it's read only; * depend on the caller to make the correct offset decisions. */ @@ -1081,12 +1212,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, if (!mem->is_flushed) global_cache_flush(); - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - writel(agp_bridge->driver->mask_memory(agp_bridge, - mem->pages[i], mask_type), intel_private.gtt+j); - } - - readl(intel_private.gtt+j-1); + intel_agp_insert_sg_entries(mem, pg_start, mask_type); agp_bridge->driver->tlb_flush(mem); out: @@ -1198,9 +1324,8 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) * this conditional. */ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, - struct page *page, int type) + dma_addr_t addr, int type) { - dma_addr_t addr = phys_to_gart(page_to_phys(page)); /* Shift high bits down */ addr |= (addr >> 28) & 0xf0; @@ -2006,6 +2131,12 @@ static const struct agp_bridge_driver intel_915_driver = { .agp_destroy_pages = agp_generic_destroy_pages, .agp_type_to_mask_type = intel_i830_type_to_mask_type, .chipset_flush = intel_i915_chipset_flush, +#ifdef USE_PCI_DMA_API + .agp_map_page = intel_agp_map_page, + .agp_unmap_page = intel_agp_unmap_page, + .agp_map_memory = intel_agp_map_memory, + .agp_unmap_memory = intel_agp_unmap_memory, +#endif }; static const struct agp_bridge_driver intel_i965_driver = { @@ -2034,6 +2165,12 @@ static const struct agp_bridge_driver intel_i965_driver = { .agp_destroy_pages = agp_generic_destroy_pages, .agp_type_to_mask_type = intel_i830_type_to_mask_type, .chipset_flush = intel_i915_chipset_flush, +#ifdef USE_PCI_DMA_API + .agp_map_page = intel_agp_map_page, + .agp_unmap_page = intel_agp_unmap_page, + .agp_map_memory = intel_agp_map_memory, + .agp_unmap_memory = intel_agp_unmap_memory, +#endif }; static const struct agp_bridge_driver intel_7505_driver = { @@ -2088,6 +2225,12 @@ static const struct agp_bridge_driver intel_g33_driver = { .agp_destroy_pages = agp_generic_destroy_pages, .agp_type_to_mask_type = intel_i830_type_to_mask_type, .chipset_flush = intel_i915_chipset_flush, +#ifdef USE_PCI_DMA_API + .agp_map_page = intel_agp_map_page, + .agp_unmap_page = intel_agp_unmap_page, + .agp_map_memory = intel_agp_map_memory, + .agp_unmap_memory = intel_agp_unmap_memory, +#endif }; static int find_gmch(u16 device) @@ -2313,15 +2456,6 @@ static int agp_intel_resume(struct pci_dev *pdev) struct agp_bridge_data *bridge = pci_get_drvdata(pdev); int ret_val; - pci_restore_state(pdev); - - /* We should restore our graphics device's config space, - * as host bridge (00:00) resumes before graphics device (02:00), - * then our access to its pci space can work right. - */ - if (intel_private.pcidev) - pci_restore_state(intel_private.pcidev); - if (bridge->driver == &intel_generic_driver) intel_configure(); else if (bridge->driver == &intel_850_driver) diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 263d71dd441..7e36d2b4f9d 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c @@ -225,7 +225,7 @@ static int nvidia_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(agp_bridge->driver->mask_memory(agp_bridge, - mem->pages[i], mask_type), + page_to_phys(mem->pages[i]), mask_type), agp_bridge->gatt_table+nvidia_private.pg_offset+j); } diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index e077701ae3d..60ab75104da 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -32,7 +32,7 @@ #define AGP8X_MODE (1 << AGP8X_MODE_BIT) static unsigned long -parisc_agp_mask_memory(struct agp_bridge_data *bridge, unsigned long addr, +parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr, int type); static struct _parisc_agp_info { @@ -189,20 +189,12 @@ parisc_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type) } static unsigned long -parisc_agp_mask_memory(struct agp_bridge_data *bridge, unsigned long addr, +parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr, int type) { return SBA_PDIR_VALID_BIT | addr; } -static unsigned long -parisc_agp_page_mask_memory(struct agp_bridge_data *bridge, struct page *page, - int type) -{ - unsigned long addr = phys_to_gart(page_to_phys(page)); - return SBA_PDIR_VALID_BIT | addr; -} - static void parisc_agp_enable(struct agp_bridge_data *bridge, u32 mode) { diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index d3ea2e4226b..0d426ae39c8 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c @@ -70,10 +70,9 @@ static void sgi_tioca_tlbflush(struct agp_memory *mem) * entry. */ static unsigned long -sgi_tioca_mask_memory(struct agp_bridge_data *bridge, - struct page *page, int type) +sgi_tioca_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr, + int type) { - unsigned long addr = phys_to_gart(page_to_phys(page)); return tioca_physpage_to_gart(addr); } @@ -190,7 +189,8 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { table[j] = - bridge->driver->mask_memory(bridge, mem->pages[i], + bridge->driver->mask_memory(bridge, + page_to_phys(mem->pages[i]), mem->type); } diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index b964a219932..13acaaf64ed 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -155,7 +155,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) /* Create a fake scratch directory */ 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); @@ -167,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 @@ -179,7 +179,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) /* 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); + writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); return 0; } @@ -349,7 +349,9 @@ 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(agp_bridge, mem->pages[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; diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index f192c3b9ad4..20ef1bf5e72 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -7,6 +7,7 @@ #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> @@ -27,6 +28,8 @@ static int uninorth_rev; static int is_u3; +#define DEFAULT_APERTURE_SIZE 256 +#define DEFAULT_APERTURE_STRING "256" static char *aperture = NULL; static int uninorth_fetch_size(void) @@ -55,7 +58,7 @@ static int uninorth_fetch_size(void) if (!size) { for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) - if (values[i].size == 32) + if (values[i].size == DEFAULT_APERTURE_SIZE) break; } @@ -135,7 +138,7 @@ 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; @@ -179,8 +182,6 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, } (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; @@ -224,7 +225,6 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) (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; @@ -243,7 +243,6 @@ int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type) for (i = 0; i < mem->page_count; ++i) gp[i] = 0; mb(); - flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]); uninorth_tlbflush(mem); return 0; @@ -396,6 +395,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) @@ -424,21 +424,39 @@ 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 + PAGE_SIZE)); + bridge->gatt_table = vmap(pages, (1 << page_order), 0, PAGE_KERNEL_NCG); + + if (bridge->gatt_table == NULL) + goto enomem; + + bridge->gatt_bus_addr = virt_to_phys(table); for (i = 0; i < num_entries; i++) bridge->gatt_table[i] = 0; - flush_dcache_range((unsigned long)table, (unsigned long)table_end); - 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) @@ -456,6 +474,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); @@ -474,13 +493,11 @@ void null_cache_flush(void) /* Setup function */ -static const 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}, @@ -491,7 +508,7 @@ static const 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 const 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}, @@ -507,7 +524,7 @@ 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, @@ -534,7 +551,7 @@ 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, @@ -717,7 +734,7 @@ 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: 32M"); + "\t\tDefault: " DEFAULT_APERTURE_STRING "M"); MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index a00869c650d..ef31738c2cb 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c @@ -2,7 +2,7 @@ * Generic /dev/nvram driver for architectures providing some * "generic" hooks, that is : * - * nvram_read_byte, nvram_write_byte, nvram_sync + * nvram_read_byte, nvram_write_byte, nvram_sync, nvram_get_size * * Note that an additional hook is supported for PowerMac only * for getting the nvram "partition" informations @@ -28,6 +28,8 @@ #define NVRAM_SIZE 8192 +static ssize_t nvram_len; + static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) { lock_kernel(); @@ -36,7 +38,7 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) offset += file->f_pos; break; case 2: - offset += NVRAM_SIZE; + offset += nvram_len; break; } if (offset < 0) { @@ -56,9 +58,9 @@ static ssize_t read_nvram(struct file *file, char __user *buf, if (!access_ok(VERIFY_WRITE, buf, count)) return -EFAULT; - if (*ppos >= NVRAM_SIZE) + if (*ppos >= nvram_len) return 0; - for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) + for (i = *ppos; count > 0 && i < nvram_len; ++i, ++p, --count) if (__put_user(nvram_read_byte(i), p)) return -EFAULT; *ppos = i; @@ -74,9 +76,9 @@ static ssize_t write_nvram(struct file *file, const char __user *buf, if (!access_ok(VERIFY_READ, buf, count)) return -EFAULT; - if (*ppos >= NVRAM_SIZE) + if (*ppos >= nvram_len) return 0; - for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) { + for (i = *ppos; count > 0 && i < nvram_len; ++i, ++p, --count) { if (__get_user(c, p)) return -EFAULT; nvram_write_byte(c, i); @@ -133,9 +135,20 @@ static struct miscdevice nvram_dev = { int __init nvram_init(void) { + int ret = 0; + printk(KERN_INFO "Generic non-volatile memory driver v%s\n", NVRAM_VERSION); - return misc_register(&nvram_dev); + ret = misc_register(&nvram_dev); + if (ret != 0) + goto out; + + nvram_len = nvram_get_size(); + if (nvram_len < 0) + nvram_len = NVRAM_SIZE; + +out: + return ret; } void __exit nvram_cleanup(void) diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index d97779ef72c..25ce15bb1c0 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -516,8 +516,6 @@ static void hvc_set_winsz(struct work_struct *work) struct winsize ws; hp = container_of(work, struct hvc_struct, tty_resize); - if (!hp) - return; spin_lock_irqsave(&hp->lock, hvc_flags); if (!hp->tty) { diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 86105efb4eb..0ecac7e532f 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c @@ -1006,7 +1006,7 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) priv->dev->release = (void (*)(struct device *)) kfree; rc = device_register(priv->dev); if (rc) { - kfree(priv->dev); + put_device(priv->dev); goto out_error_dev; } diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index c72b994652a..10be343d6ae 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -120,7 +120,7 @@ static struct vio_driver hvc_vio_driver = { } }; -static int hvc_vio_init(void) +static int __init hvc_vio_init(void) { int rc; @@ -134,7 +134,7 @@ static int hvc_vio_init(void) } module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ -static void hvc_vio_exit(void) +static void __exit hvc_vio_exit(void) { vio_unregister_driver(&hvc_vio_driver); } diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 2989056a9e3..793b236c926 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -1230,11 +1230,12 @@ static struct tty_driver *hvsi_console_device(struct console *console, static int __init hvsi_console_setup(struct console *console, char *options) { - struct hvsi_struct *hp = &hvsi_ports[console->index]; + struct hvsi_struct *hp; int ret; if (console->index < 0 || console->index >= hvsi_count) return -1; + hp = &hvsi_ports[console->index]; /* give the FSP a chance to change the baud rate when we re-open */ hvsi_close_protocol(hp); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index ce66a70184f..87060266ef9 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -126,6 +126,19 @@ config HW_RANDOM_OMAP If unsure, say Y. +config HW_RANDOM_OCTEON + tristate "Octeon Random Number Generator support" + depends on HW_RANDOM && CPU_CAVIUM_OCTEON + default HW_RANDOM + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on Octeon processors. + + To compile this driver as a module, choose M here: the + module will be called octeon-rng. + + If unsure, say Y. + config HW_RANDOM_PASEMI tristate "PA Semi HW Random Number Generator support" depends on HW_RANDOM && PPC_PASEMI diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 676828ba812..5eeb1303f0d 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o +obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index cd0ba51f7c8..0d8c5788b8e 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c @@ -44,8 +44,8 @@ * want to register another driver on the same PCI id. */ static const struct pci_device_id pci_tbl[] = { - { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, - { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { PCI_VDEVICE(AMD, 0x7443), 0, }, + { PCI_VDEVICE(AMD, 0x746b), 0, }, { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c index 64d513f6836..4c4d4e140f9 100644 --- a/drivers/char/hw_random/geode-rng.c +++ b/drivers/char/hw_random/geode-rng.c @@ -46,8 +46,7 @@ * want to register another driver on the same PCI id. */ static const struct pci_device_id pci_tbl[] = { - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_LX_AES), 0, }, { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, pci_tbl); diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c new file mode 100644 index 00000000000..54b0d9ba65c --- /dev/null +++ b/drivers/char/hw_random/octeon-rng.c @@ -0,0 +1,147 @@ +/* + * Hardware Random Number Generator support for Cavium Networks + * Octeon processor family. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2009 Cavium Networks + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/device.h> +#include <linux/hw_random.h> +#include <linux/io.h> + +#include <asm/octeon/octeon.h> +#include <asm/octeon/cvmx-rnm-defs.h> + +struct octeon_rng { + struct hwrng ops; + void __iomem *control_status; + void __iomem *result; +}; + +static int octeon_rng_init(struct hwrng *rng) +{ + union cvmx_rnm_ctl_status ctl; + struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); + + ctl.u64 = 0; + ctl.s.ent_en = 1; /* Enable the entropy source. */ + ctl.s.rng_en = 1; /* Enable the RNG hardware. */ + cvmx_write_csr((u64)p->control_status, ctl.u64); + return 0; +} + +static void octeon_rng_cleanup(struct hwrng *rng) +{ + union cvmx_rnm_ctl_status ctl; + struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); + + ctl.u64 = 0; + /* Disable everything. */ + cvmx_write_csr((u64)p->control_status, ctl.u64); +} + +static int octeon_rng_data_read(struct hwrng *rng, u32 *data) +{ + struct octeon_rng *p = container_of(rng, struct octeon_rng, ops); + + *data = cvmx_read64_uint32((u64)p->result); + return sizeof(u32); +} + +static int __devinit octeon_rng_probe(struct platform_device *pdev) +{ + struct resource *res_ports; + struct resource *res_result; + struct octeon_rng *rng; + int ret; + struct hwrng ops = { + .name = "octeon", + .init = octeon_rng_init, + .cleanup = octeon_rng_cleanup, + .data_read = octeon_rng_data_read + }; + + rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); + if (!rng) + return -ENOMEM; + + res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res_ports) + goto err_ports; + + res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res_result) + goto err_ports; + + + rng->control_status = devm_ioremap_nocache(&pdev->dev, + res_ports->start, + sizeof(u64)); + if (!rng->control_status) + goto err_ports; + + rng->result = devm_ioremap_nocache(&pdev->dev, + res_result->start, + sizeof(u64)); + if (!rng->result) + goto err_r; + + rng->ops = ops; + + dev_set_drvdata(&pdev->dev, &rng->ops); + ret = hwrng_register(&rng->ops); + if (ret) + goto err; + + dev_info(&pdev->dev, "Octeon Random Number Generator\n"); + + return 0; +err: + devm_iounmap(&pdev->dev, rng->control_status); +err_r: + devm_iounmap(&pdev->dev, rng->result); +err_ports: + devm_kfree(&pdev->dev, rng); + return -ENOENT; +} + +static int __exit octeon_rng_remove(struct platform_device *pdev) +{ + struct hwrng *rng = dev_get_drvdata(&pdev->dev); + + hwrng_unregister(rng); + + return 0; +} + +static struct platform_driver octeon_rng_driver = { + .driver = { + .name = "octeon_rng", + .owner = THIS_MODULE, + }, + .probe = octeon_rng_probe, + .remove = __exit_p(octeon_rng_remove), +}; + +static int __init octeon_rng_mod_init(void) +{ + return platform_driver_register(&octeon_rng_driver); +} + +static void __exit octeon_rng_mod_exit(void) +{ + platform_driver_unregister(&octeon_rng_driver); +} + +module_init(octeon_rng_mod_init); +module_exit(octeon_rng_mod_exit); + +MODULE_AUTHOR("David Daney"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index acd8e9ed474..87c67b42bc0 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c @@ -15,6 +15,7 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/ioport.h> +#include <linux/kernel.h> #include <linux/notifier.h> #include <linux/reboot.h> #include <linux/init.h> @@ -715,8 +716,8 @@ static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char */ debug0 = *(uint64_t *) soft->debug_addr; - return sprintf(buf, "0x%lx 0x%lx\n", - (debug0 >> 32), (debug0 & 0xffffffff)); + return sprintf(buf, "0x%x 0x%x\n", + upper_32_bits(debug0), lower_32_bits(debug0)); } static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index afa8813e737..0491cdf63f2 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -822,6 +822,7 @@ static const struct file_operations zero_fops = { * - permits private mappings, "copies" are taken of the source of zeros */ static struct backing_dev_info zero_bdi = { + .name = "char/mem", .capabilities = BDI_CAP_MAP_COPY, }; @@ -863,71 +864,67 @@ static const struct file_operations kmsg_fops = { .write = kmsg_write, }; -static const struct { - unsigned int minor; - char *name; - umode_t mode; - const struct file_operations *fops; - struct backing_dev_info *dev_info; -} devlist[] = { /* list of minor devices */ - {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops, - &directly_mappable_cdev_bdi}, +static const struct memdev { + const char *name; + const struct file_operations *fops; + struct backing_dev_info *dev_info; +} devlist[] = { + [ 1] = { "mem", &mem_fops, &directly_mappable_cdev_bdi }, #ifdef CONFIG_DEVKMEM - {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops, - &directly_mappable_cdev_bdi}, + [ 2] = { "kmem", &kmem_fops, &directly_mappable_cdev_bdi }, #endif - {3, "null", S_IRUGO | S_IWUGO, &null_fops, NULL}, + [ 3] = {"null", &null_fops, NULL }, #ifdef CONFIG_DEVPORT - {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops, NULL}, + [ 4] = { "port", &port_fops, NULL }, #endif - {5, "zero", S_IRUGO | S_IWUGO, &zero_fops, &zero_bdi}, - {7, "full", S_IRUGO | S_IWUGO, &full_fops, NULL}, - {8, "random", S_IRUGO | S_IWUSR, &random_fops, NULL}, - {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops, NULL}, - {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops, NULL}, + [ 5] = { "zero", &zero_fops, &zero_bdi }, + [ 7] = { "full", &full_fops, NULL }, + [ 8] = { "random", &random_fops, NULL }, + [ 9] = { "urandom", &urandom_fops, NULL }, + [11] = { "kmsg", &kmsg_fops, NULL }, #ifdef CONFIG_CRASH_DUMP - {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops, NULL}, + [12] = { "oldmem", &oldmem_fops, NULL }, #endif }; static int memory_open(struct inode *inode, struct file *filp) { - int ret = 0; - int i; + int minor; + const struct memdev *dev; + int ret = -ENXIO; lock_kernel(); - for (i = 0; i < ARRAY_SIZE(devlist); i++) { - if (devlist[i].minor == iminor(inode)) { - filp->f_op = devlist[i].fops; - if (devlist[i].dev_info) { - filp->f_mapping->backing_dev_info = - devlist[i].dev_info; - } + minor = iminor(inode); + if (minor >= ARRAY_SIZE(devlist)) + goto out; - break; - } - } + dev = &devlist[minor]; + if (!dev->fops) + goto out; - if (i == ARRAY_SIZE(devlist)) - ret = -ENXIO; - else - if (filp->f_op && filp->f_op->open) - ret = filp->f_op->open(inode, filp); + filp->f_op = dev->fops; + if (dev->dev_info) + filp->f_mapping->backing_dev_info = dev->dev_info; + if (dev->fops->open) + ret = dev->fops->open(inode, filp); + else + ret = 0; +out: unlock_kernel(); return ret; } static const struct file_operations memory_fops = { - .open = memory_open, /* just a selector for the real open */ + .open = memory_open, }; static struct class *mem_class; static int __init chr_dev_init(void) { - int i; + int minor; int err; err = bdi_init(&zero_bdi); @@ -938,10 +935,12 @@ static int __init chr_dev_init(void) printk("unable to get major %d for memory devs\n", MEM_MAJOR); mem_class = class_create(THIS_MODULE, "mem"); - for (i = 0; i < ARRAY_SIZE(devlist); i++) - device_create(mem_class, NULL, - MKDEV(MEM_MAJOR, devlist[i].minor), NULL, - devlist[i].name); + for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { + if (!devlist[minor].name) + continue; + device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor), + NULL, devlist[minor].name); + } return 0; } diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 77b36488922..caf6e4d1946 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -4005,10 +4005,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, * * skb socket buffer containing HDLC frame * dev pointer to network device structure - * - * returns 0 if success, otherwise error code */ -static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, + struct net_device *dev) { MGSLPC_INFO *info = dev_to_port(dev); unsigned long flags; @@ -4043,7 +4042,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) } spin_unlock_irqrestore(&info->lock,flags); - return 0; + return NETDEV_TX_OK; } /** diff --git a/drivers/char/pty.c b/drivers/char/pty.c index b33d6688e91..53761cefa91 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -120,8 +120,10 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to, buf, c); /* And shovel */ - tty_flip_buffer_push(to); - tty_wakeup(tty); + if (c) { + tty_flip_buffer_push(to); + tty_wakeup(tty); + } } return c; } diff --git a/drivers/char/random.c b/drivers/char/random.c index 8c7444857a4..d8a9255e1a3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -240,6 +240,7 @@ #include <linux/spinlock.h> #include <linux/percpu.h> #include <linux/cryptohash.h> +#include <linux/fips.h> #ifdef CONFIG_GENERIC_HARDIRQS # include <linux/irq.h> @@ -413,6 +414,7 @@ struct entropy_store { unsigned add_ptr; int entropy_count; int input_rotate; + __u8 *last_data; }; static __u32 input_pool_data[INPUT_POOL_WORDS]; @@ -852,12 +854,21 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, { ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; + unsigned long flags; xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); while (nbytes) { extract_buf(r, tmp); + + if (r->last_data) { + spin_lock_irqsave(&r->lock, flags); + if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) + panic("Hardware RNG duplicated output!\n"); + memcpy(r->last_data, tmp, EXTRACT_SIZE); + spin_unlock_irqrestore(&r->lock, flags); + } i = min_t(int, nbytes, EXTRACT_SIZE); memcpy(buf, tmp, i); nbytes -= i; @@ -940,6 +951,9 @@ static void init_std_data(struct entropy_store *r) now = ktime_get_real(); mix_pool_bytes(r, &now, sizeof(now)); mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); + /* Enable continuous test in fips mode */ + if (fips_enabled) + r->last_data = kmalloc(EXTRACT_SIZE, GFP_KERNEL); } static int rand_initialize(void) diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 05f9d18b936..40268db02e2 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -246,7 +246,7 @@ static const struct file_operations raw_fops = { .read = do_sync_read, .aio_read = generic_file_aio_read, .write = do_sync_write, - .aio_write = generic_file_aio_write_nolock, + .aio_write = blkdev_aio_write, .open = raw_open, .release= raw_release, .ioctl = raw_ioctl, diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 51e7a46787b..5942a9d674c 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -171,7 +171,6 @@ static int startup(struct cyclades_port *); static void cy_throttle(struct tty_struct *); static void cy_unthrottle(struct tty_struct *); static void config_setup(struct cyclades_port *); -extern void console_print(const char *); #ifdef CYCLOM_SHOW_STATUS static void show_status(int); #endif @@ -245,7 +244,7 @@ void SP(char *data) { unsigned long flags; local_irq_save(flags); - console_print(data); + printk(KERN_EMERG "%s", data); local_irq_restore(flags); } @@ -255,7 +254,7 @@ void CP(char data) unsigned long flags; local_irq_save(flags); scrn[0] = data; - console_print(scrn); + printk(KERN_EMERG "%c", scrn); local_irq_restore(flags); } /* CP */ diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 813552f1488..4846b73ef28 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -7697,10 +7697,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, * * skb socket buffer containing HDLC frame * dev pointer to network device structure - * - * returns 0 if success, otherwise error code */ -static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, + struct net_device *dev) { struct mgsl_struct *info = dev_to_port(dev); unsigned long flags; @@ -7731,7 +7730,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) usc_start_transmitter(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); - return 0; + return NETDEV_TX_OK; } /** diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 91f20a92fdd..8678f0c8699 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1497,10 +1497,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, * * skb socket buffer containing HDLC frame * dev pointer to network device structure - * - * returns 0 if success, otherwise error code */ -static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, + struct net_device *dev) { struct slgt_info *info = dev_to_port(dev); unsigned long flags; @@ -1529,7 +1528,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) update_tx_timer(info); spin_unlock_irqrestore(&info->lock,flags); - return 0; + return NETDEV_TX_OK; } /** diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8d4a2a8a0a7..2b18adc4ee1 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1608,10 +1608,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, * * skb socket buffer containing HDLC frame * dev pointer to network device structure - * - * returns 0 if success, otherwise error code */ -static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb, + struct net_device *dev) { SLMP_INFO *info = dev_to_port(dev); unsigned long flags; @@ -1642,7 +1641,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) tx_start(info); spin_unlock_irqrestore(&info->lock,flags); - return 0; + return NETDEV_TX_OK; } /** diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 5d7a02f63e1..50eecfe1d72 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -24,6 +24,7 @@ #include <linux/sysrq.h> #include <linux/kbd_kern.h> #include <linux/proc_fs.h> +#include <linux/nmi.h> #include <linux/quotaops.h> #include <linux/perf_counter.h> #include <linux/kernel.h> @@ -222,12 +223,20 @@ static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus); static void sysrq_handle_showallcpus(int key, struct tty_struct *tty) { - struct pt_regs *regs = get_irq_regs(); - if (regs) { - printk(KERN_INFO "CPU%d:\n", smp_processor_id()); - show_regs(regs); + /* + * Fall back to the workqueue based printing if the + * backtrace printing did not succeed or the + * architecture has no support for it: + */ + if (!trigger_all_cpu_backtrace()) { + struct pt_regs *regs = get_irq_regs(); + + if (regs) { + printk(KERN_INFO "CPU%d:\n", smp_processor_id()); + show_regs(regs); + } + schedule_work(&sysrq_showallcpus); } - schedule_work(&sysrq_showallcpus); } static struct sysrq_key_op sysrq_showallcpus_op = { diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index aec1931608a..0b73e4ec1ad 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -450,6 +450,12 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, goto out_err; } + /* Default timeouts */ + chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); + chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + if (request_locality(chip, 0) != 0) { rc = -ENODEV; goto out_err; @@ -457,12 +463,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); - /* Default timeouts */ - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - dev_info(dev, "1.2 TPM (device-id 0x%X, rev-id %d)\n", vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 404f4c1ee43..6aa88f50b03 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2948,9 +2948,6 @@ int __init vty_init(const struct file_operations *console_fops) panic("Couldn't register console driver\n"); kbd_init(); console_map_init(); -#ifdef CONFIG_PROM_CONSOLE - prom_con_init(); -#endif #ifdef CONFIG_MDA_CONSOLE mda_console_init(); #endif |