Commit 7c8f486a authored by David S. Miller's avatar David S. Miller

[SPARC64]: Fix IOMMU mapping on sun4v.

We should dynamically allocate the per-cpu pglist not use
an in-kernel-image datum, since __pa() does not work on
such addresses.

Also, consistently use "u32" for devhandle.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 87bdc367
...@@ -24,10 +24,10 @@ ...@@ -24,10 +24,10 @@
#include "pci_sun4v.h" #include "pci_sun4v.h"
#define PGLIST_NENTS 2048 #define PGLIST_NENTS (PAGE_SIZE / sizeof(u64))
struct sun4v_pglist { struct sun4v_pglist {
u64 pglist[PGLIST_NENTS]; u64 *pglist;
}; };
static DEFINE_PER_CPU(struct sun4v_pglist, iommu_pglists); static DEFINE_PER_CPU(struct sun4v_pglist, iommu_pglists);
...@@ -83,10 +83,11 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr ...@@ -83,10 +83,11 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
{ {
struct pcidev_cookie *pcp; struct pcidev_cookie *pcp;
struct pci_iommu *iommu; struct pci_iommu *iommu;
unsigned long devhandle, flags, order, first_page, npages, n; unsigned long flags, order, first_page, npages, n;
void *ret; void *ret;
long entry; long entry;
u64 *pglist; u64 *pglist;
u32 devhandle;
int cpu; int cpu;
size = IO_PAGE_ALIGN(size); size = IO_PAGE_ALIGN(size);
...@@ -123,7 +124,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr ...@@ -123,7 +124,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
cpu = get_cpu(); cpu = get_cpu();
pglist = &__get_cpu_var(iommu_pglists).pglist[0]; pglist = __get_cpu_var(iommu_pglists).pglist;
for (n = 0; n < npages; n++) for (n = 0; n < npages; n++)
pglist[n] = first_page + (n * PAGE_SIZE); pglist[n] = first_page + (n * PAGE_SIZE);
...@@ -149,7 +150,8 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, ...@@ -149,7 +150,8 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
{ {
struct pcidev_cookie *pcp; struct pcidev_cookie *pcp;
struct pci_iommu *iommu; struct pci_iommu *iommu;
unsigned long flags, order, npages, entry, devhandle; unsigned long flags, order, npages, entry;
u32 devhandle;
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
pcp = pdev->sysdata; pcp = pdev->sysdata;
...@@ -182,8 +184,8 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, ...@@ -182,8 +184,8 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
struct pcidev_cookie *pcp; struct pcidev_cookie *pcp;
struct pci_iommu *iommu; struct pci_iommu *iommu;
unsigned long flags, npages, oaddr; unsigned long flags, npages, oaddr;
unsigned long i, base_paddr, devhandle; unsigned long i, base_paddr;
u32 bus_addr, ret; u32 devhandle, bus_addr, ret;
unsigned long prot; unsigned long prot;
long entry; long entry;
u64 *pglist; u64 *pglist;
...@@ -219,7 +221,7 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, ...@@ -219,7 +221,7 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
cpu = get_cpu(); cpu = get_cpu();
pglist = &__get_cpu_var(iommu_pglists).pglist[0]; pglist = __get_cpu_var(iommu_pglists).pglist;
for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE) for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE)
pglist[i] = base_paddr; pglist[i] = base_paddr;
...@@ -248,8 +250,9 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ ...@@ -248,8 +250,9 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
{ {
struct pcidev_cookie *pcp; struct pcidev_cookie *pcp;
struct pci_iommu *iommu; struct pci_iommu *iommu;
unsigned long flags, npages, devhandle; unsigned long flags, npages;
long entry; long entry;
u32 devhandle;
if (unlikely(direction == PCI_DMA_NONE)) { if (unlikely(direction == PCI_DMA_NONE)) {
if (printk_ratelimit()) if (printk_ratelimit())
...@@ -285,7 +288,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_ ...@@ -285,7 +288,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
#define SG_ENT_PHYS_ADDRESS(SG) \ #define SG_ENT_PHYS_ADDRESS(SG) \
(__pa(page_address((SG)->page)) + (SG)->offset) (__pa(page_address((SG)->page)) + (SG)->offset)
static inline void fill_sg(long entry, unsigned long devhandle, static inline void fill_sg(long entry, u32 devhandle,
struct scatterlist *sg, struct scatterlist *sg,
int nused, int nelems, unsigned long prot) int nused, int nelems, unsigned long prot)
{ {
...@@ -295,7 +298,7 @@ static inline void fill_sg(long entry, unsigned long devhandle, ...@@ -295,7 +298,7 @@ static inline void fill_sg(long entry, unsigned long devhandle,
u64 *pglist; u64 *pglist;
cpu = get_cpu(); cpu = get_cpu();
pglist = &__get_cpu_var(iommu_pglists).pglist[0]; pglist = __get_cpu_var(iommu_pglists).pglist;
pglist_ent = 0; pglist_ent = 0;
for (i = 0; i < nused; i++) { for (i = 0; i < nused; i++) {
unsigned long pteval = ~0UL; unsigned long pteval = ~0UL;
...@@ -380,8 +383,8 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n ...@@ -380,8 +383,8 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
{ {
struct pcidev_cookie *pcp; struct pcidev_cookie *pcp;
struct pci_iommu *iommu; struct pci_iommu *iommu;
unsigned long flags, npages, prot, devhandle; unsigned long flags, npages, prot;
u32 dma_base; u32 devhandle, dma_base;
struct scatterlist *sgtmp; struct scatterlist *sgtmp;
long entry; long entry;
int used; int used;
...@@ -451,9 +454,9 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in ...@@ -451,9 +454,9 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
{ {
struct pcidev_cookie *pcp; struct pcidev_cookie *pcp;
struct pci_iommu *iommu; struct pci_iommu *iommu;
unsigned long flags, i, npages, devhandle; unsigned long flags, i, npages;
long entry; long entry;
u32 bus_addr; u32 devhandle, bus_addr;
if (unlikely(direction == PCI_DMA_NONE)) { if (unlikely(direction == PCI_DMA_NONE)) {
if (printk_ratelimit()) if (printk_ratelimit())
...@@ -805,7 +808,8 @@ static void probe_existing_entries(struct pci_pbm_info *pbm, ...@@ -805,7 +808,8 @@ static void probe_existing_entries(struct pci_pbm_info *pbm,
struct pci_iommu *iommu) struct pci_iommu *iommu)
{ {
struct pci_iommu_arena *arena = &iommu->arena; struct pci_iommu_arena *arena = &iommu->arena;
unsigned long i, devhandle; unsigned long i;
u32 devhandle;
devhandle = pbm->devhandle; devhandle = pbm->devhandle;
for (i = 0; i < arena->limit; i++) { for (i = 0; i < arena->limit; i++) {
...@@ -906,7 +910,7 @@ static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm) ...@@ -906,7 +910,7 @@ static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
} }
static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, unsigned int devhandle) static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle)
{ {
struct pci_pbm_info *pbm; struct pci_pbm_info *pbm;
int err, i; int err, i;
...@@ -978,7 +982,8 @@ void sun4v_pci_init(int node, char *model_name) ...@@ -978,7 +982,8 @@ void sun4v_pci_init(int node, char *model_name)
struct pci_controller_info *p; struct pci_controller_info *p;
struct pci_iommu *iommu; struct pci_iommu *iommu;
struct linux_prom64_registers regs; struct linux_prom64_registers regs;
unsigned int devhandle; u32 devhandle;
int i;
prom_getproperty(node, "reg", (char *)&regs, sizeof(regs)); prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff; devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff;
...@@ -999,26 +1004,32 @@ void sun4v_pci_init(int node, char *model_name) ...@@ -999,26 +1004,32 @@ void sun4v_pci_init(int node, char *model_name)
} }
} }
p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); for (i = 0; i < NR_CPUS; i++) {
if (!p) { unsigned long page = get_zeroed_page(GFP_ATOMIC);
prom_printf("SUN4V_PCI: Fatal memory allocation error.\n");
prom_halt(); if (!page)
goto fatal_memory_error;
per_cpu(iommu_pglists, i).pglist = (u64 *) page;
} }
p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p)
goto fatal_memory_error;
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) { if (!iommu)
prom_printf("SCHIZO: Fatal memory allocation error.\n"); goto fatal_memory_error;
prom_halt();
}
memset(iommu, 0, sizeof(*iommu)); memset(iommu, 0, sizeof(*iommu));
p->pbm_A.iommu = iommu; p->pbm_A.iommu = iommu;
iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC); iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
if (!iommu) { if (!iommu)
prom_printf("SCHIZO: Fatal memory allocation error.\n"); goto fatal_memory_error;
prom_halt();
}
memset(iommu, 0, sizeof(*iommu)); memset(iommu, 0, sizeof(*iommu));
p->pbm_B.iommu = iommu; p->pbm_B.iommu = iommu;
...@@ -1040,4 +1051,9 @@ void sun4v_pci_init(int node, char *model_name) ...@@ -1040,4 +1051,9 @@ void sun4v_pci_init(int node, char *model_name)
pci_memspace_mask = 0x7fffffffUL; pci_memspace_mask = 0x7fffffffUL;
pci_sun4v_pbm_init(p, node, devhandle); pci_sun4v_pbm_init(p, node, devhandle);
return;
fatal_memory_error:
prom_printf("SUN4V_PCI: Fatal memory allocation error.\n");
prom_halt();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment