aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-06-04 01:15:36 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-14 08:29:56 -0400
commit3d5134ee8341bffc4f539049abb9e90d469b448d (patch)
tree037958e0daa97b4ef350908a53182167ee2c8a03 /include
parentc19c03fc749147f565e807fa65f1729066800571 (diff)
[POWERPC] Rewrite IO allocation & mapping on powerpc64
This rewrites pretty much from scratch the handling of MMIO and PIO space allocations on powerpc64. The main goals are: - Get rid of imalloc and use more common code where possible - Simplify the current mess so that PIO space is allocated and mapped in a single place for PCI bridges - Handle allocation constraints of PIO for all bridges including hot plugged ones within the 2GB space reserved for IO ports, so that devices on hotplugged busses will now work with drivers that assume IO ports fit in an int. - Cleanup and separate tracking of the ISA space in the reserved low 64K of IO space. No ISA -> Nothing mapped there. I booted a cell blade with IDE on PIO and MMIO and a dual G5 so far, that's it :-) With this patch, all allocations are done using the code in mm/vmalloc.c, though we use the low level __get_vm_area with explicit start/stop constraints in order to manage separate areas for vmalloc/vmap, ioremap, and PCI IOs. This greatly simplifies a lot of things, as you can see in the diffstat of that patch :-) A new pair of functions pcibios_map/unmap_io_space() now replace all of the previous code that used to manipulate PCI IOs space. The allocation is done at mapping time, which is now called from scan_phb's, just before the devices are probed (instead of after, which is by itself a bug fix). The only other caller is the PCI hotplug code for hot adding PCI-PCI bridges (slots). imalloc is gone, as is the "sub-allocation" thing, but I do beleive that hotplug should still work in the sense that the space allocation is always done by the PHB, but if you unmap a child bus of this PHB (which seems to be possible), then the code should properly tear down all the HPTE mappings for that area of the PHB allocated IO space. I now always reserve the first 64K of IO space for the bridge with the ISA bus on it. I have moved the code for tracking ISA in a separate file which should also make it smarter if we ever are capable of hot unplugging or re-plugging an ISA bridge. This should have a side effect on platforms like powermac where VGA IOs will no longer work. This is done on purpose though as they would have worked semi-randomly before. The idea at this point is to isolate drivers that might need to access those and fix them by providing a proper function to obtain an offset to the legacy IOs of a given bus. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include')
-rw-r--r--include/asm-powerpc/floppy.h6
-rw-r--r--include/asm-powerpc/io.h19
-rw-r--r--include/asm-powerpc/pci-bridge.h6
-rw-r--r--include/asm-powerpc/pci.h4
-rw-r--r--include/asm-powerpc/pgtable-ppc64.h21
-rw-r--r--include/asm-powerpc/ppc-pci.h6
-rw-r--r--include/asm-powerpc/tlbflush.h5
7 files changed, 40 insertions, 27 deletions
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index afa700ded877..34146f0eea63 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -29,7 +29,7 @@
29#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); 29#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
30 30
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <asm/ppc-pci.h> /* for ppc64_isabridge_dev */ 32#include <asm/ppc-pci.h> /* for isa_bridge_pcidev */
33 33
34#define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io) 34#define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io)
35 35
@@ -139,12 +139,12 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
139 if (bus_addr 139 if (bus_addr
140 && (addr != prev_addr || size != prev_size || dir != prev_dir)) { 140 && (addr != prev_addr || size != prev_size || dir != prev_dir)) {
141 /* different from last time -- unmap prev */ 141 /* different from last time -- unmap prev */
142 pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir); 142 pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir);
143 bus_addr = 0; 143 bus_addr = 0;
144 } 144 }
145 145
146 if (!bus_addr) /* need to map it */ 146 if (!bus_addr) /* need to map it */
147 bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir); 147 bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir);
148 148
149 /* remember this one as prev */ 149 /* remember this one as prev */
150 prev_addr = addr; 150 prev_addr = addr;
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 350c9bdb31dc..17efea5b594c 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -607,9 +607,9 @@ static inline void iosync(void)
607 * 607 *
608 * * iounmap undoes such a mapping and can be hooked 608 * * iounmap undoes such a mapping and can be hooked
609 * 609 *
610 * * __ioremap_explicit (and the pending __iounmap_explicit) are low level 610 * * __ioremap_at (and the pending __iounmap_at) are low level functions to
611 * functions to create hand-made mappings for use only by the PCI code 611 * create hand-made mappings for use only by the PCI code and cannot
612 * and cannot currently be hooked. 612 * currently be hooked. Must be page aligned.
613 * 613 *
614 * * __ioremap is the low level implementation used by ioremap and 614 * * __ioremap is the low level implementation used by ioremap and
615 * ioremap_flags and cannot be hooked (but can be used by a hook on one 615 * ioremap_flags and cannot be hooked (but can be used by a hook on one
@@ -629,12 +629,9 @@ extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
629 unsigned long flags); 629 unsigned long flags);
630extern void __iounmap(volatile void __iomem *addr); 630extern void __iounmap(volatile void __iomem *addr);
631 631
632extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr, 632extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
633 unsigned long size, unsigned long flags); 633 unsigned long size, unsigned long flags);
634extern int __iounmap_explicit(volatile void __iomem *start, 634extern void __iounmap_at(void *ea, unsigned long size);
635 unsigned long size);
636
637extern void __iomem * reserve_phb_iospace(unsigned long size);
638 635
639/* Those are more 32 bits only functions */ 636/* Those are more 32 bits only functions */
640extern unsigned long iopa(unsigned long addr); 637extern unsigned long iopa(unsigned long addr);
@@ -651,8 +648,8 @@ extern void io_block_mapping(unsigned long virt, phys_addr_t phys,
651 */ 648 */
652#define HAVE_ARCH_PIO_SIZE 1 649#define HAVE_ARCH_PIO_SIZE 1
653#define PIO_OFFSET 0x00000000UL 650#define PIO_OFFSET 0x00000000UL
654#define PIO_MASK 0x3fffffffUL 651#define PIO_MASK (FULL_IO_SIZE - 1)
655#define PIO_RESERVED 0x40000000UL 652#define PIO_RESERVED (FULL_IO_SIZE)
656 653
657#define mmio_read16be(addr) readw_be(addr) 654#define mmio_read16be(addr) readw_be(addr)
658#define mmio_read32be(addr) readl_be(addr) 655#define mmio_read32be(addr) readl_be(addr)
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index c49ce41cfa95..5261527ed7b1 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -31,6 +31,7 @@ struct pci_controller {
31 int last_busno; 31 int last_busno;
32 32
33 void __iomem *io_base_virt; 33 void __iomem *io_base_virt;
34 void *io_base_alloc;
34 resource_size_t io_base_phys; 35 resource_size_t io_base_phys;
35 36
36 /* Some machines have a non 1:1 mapping of 37 /* Some machines have a non 1:1 mapping of
@@ -167,6 +168,11 @@ static inline unsigned long pci_address_to_pio(phys_addr_t address)
167} 168}
168#endif 169#endif
169 170
171extern void isa_bridge_find_early(struct pci_controller *hose);
172
173extern int pcibios_unmap_io_space(struct pci_bus *bus);
174extern int pcibios_map_io_space(struct pci_bus *bus);
175
170/* Return values for ppc_md.pci_probe_mode function */ 176/* Return values for ppc_md.pci_probe_mode function */
171#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ 177#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */
172#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ 178#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index ce0f13e8eb14..93e3752df6b7 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -220,10 +220,6 @@ static inline struct resource *pcibios_select_root(struct pci_dev *pdev,
220 return root; 220 return root;
221} 221}
222 222
223extern int unmap_bus_range(struct pci_bus *bus);
224
225extern int remap_bus_range(struct pci_bus *bus);
226
227extern void pcibios_fixup_device_resources(struct pci_dev *dev, 223extern void pcibios_fixup_device_resources(struct pci_dev *dev,
228 struct pci_bus *bus); 224 struct pci_bus *bus);
229 225
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index 704c4e669fe0..9b0f51ccad05 100644
--- a/include/asm-powerpc/pgtable-ppc64.h
+++ b/include/asm-powerpc/pgtable-ppc64.h
@@ -27,7 +27,7 @@ struct mm_struct;
27 */ 27 */
28#define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ 28#define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
29 PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT) 29 PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
30#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE) 30#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE)
31 31
32#if TASK_SIZE_USER64 > PGTABLE_RANGE 32#if TASK_SIZE_USER64 > PGTABLE_RANGE
33#error TASK_SIZE_USER64 exceeds pagetable range 33#error TASK_SIZE_USER64 exceeds pagetable range
@@ -37,19 +37,28 @@ struct mm_struct;
37#error TASK_SIZE_USER64 exceeds user VSID range 37#error TASK_SIZE_USER64 exceeds user VSID range
38#endif 38#endif
39 39
40
40/* 41/*
41 * Define the address range of the vmalloc VM area. 42 * Define the address range of the vmalloc VM area.
42 */ 43 */
43#define VMALLOC_START ASM_CONST(0xD000000000000000) 44#define VMALLOC_START ASM_CONST(0xD000000000000000)
44#define VMALLOC_SIZE ASM_CONST(0x80000000000) 45#define VMALLOC_SIZE (PGTABLE_RANGE >> 1)
45#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) 46#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
46 47
47/* 48/*
48 * Define the address range of the imalloc VM area. 49 * Define the address ranges for MMIO and IO space :
50 *
51 * ISA_IO_BASE = VMALLOC_END, 64K reserved area
52 * PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
53 * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
49 */ 54 */
50#define PHBS_IO_BASE VMALLOC_END 55#define FULL_IO_SIZE 0x80000000ul
51#define IMALLOC_BASE (PHBS_IO_BASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */ 56#define ISA_IO_BASE (VMALLOC_END)
52#define IMALLOC_END (VMALLOC_START + PGTABLE_RANGE) 57#define ISA_IO_END (VMALLOC_END + 0x10000ul)
58#define PHB_IO_BASE (ISA_IO_END)
59#define PHB_IO_END (VMALLOC_END + FULL_IO_SIZE)
60#define IOREMAP_BASE (PHB_IO_END)
61#define IOREMAP_END (VMALLOC_START + PGTABLE_RANGE)
53 62
54/* 63/*
55 * Region IDs 64 * Region IDs
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index 2a6ac69cadc9..b847aa10074b 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -26,7 +26,7 @@ extern int global_phb_number;
26 26
27extern void find_and_init_phbs(void); 27extern void find_and_init_phbs(void);
28 28
29extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ 29extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */
30 30
31/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ 31/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
32#define BUID_HI(buid) ((buid) >> 32) 32#define BUID_HI(buid) ((buid) >> 32)
@@ -47,8 +47,8 @@ extern void init_pci_config_tokens (void);
47extern unsigned long get_phb_buid (struct device_node *); 47extern unsigned long get_phb_buid (struct device_node *);
48extern int rtas_setup_phb(struct pci_controller *phb); 48extern int rtas_setup_phb(struct pci_controller *phb);
49 49
50/* From pSeries_pci.h */ 50/* From iSeries PCI */
51extern void pSeries_final_fixup(void); 51extern void iSeries_pcibios_init(void);
52 52
53extern unsigned long pci_probe_only; 53extern unsigned long pci_probe_only;
54 54
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index 86e6266a028b..99a0439baa50 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -155,6 +155,11 @@ static inline void flush_tlb_kernel_range(unsigned long start,
155{ 155{
156} 156}
157 157
158/* Private function for use by PCI IO mapping code */
159extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
160 unsigned long end);
161
162
158#endif 163#endif
159 164
160/* 165/*