diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-02-10 00:32:07 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-20 04:12:10 -0500 |
commit | 8f6a93a196ba6c569c3e8daa6e81cca7e3ba81b1 (patch) | |
tree | 80d4747608148c56fd8c67baf016ad4fc58610ea /arch/sparc64 | |
parent | 4cce4b7cc56abc3d7b269d09224b8297aad15138 (diff) |
[SPARC64]: Beginnings of SUN4V PCI controller support.
Abstract out IOMMU operations so that we can have a different
set of calls on sun4v, which needs to do things through
hypervisor calls.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci.c | 13 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_iommu.c | 27 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 74 |
4 files changed, 107 insertions, 9 deletions
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index a482a9ffe5bc..44043390e34f 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile | |||
@@ -14,7 +14,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ | |||
14 | power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o | 14 | power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o |
15 | 15 | ||
16 | obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ | 16 | obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ |
17 | pci_psycho.o pci_sabre.o pci_schizo.o | 17 | pci_psycho.o pci_sabre.o pci_schizo.o pci_sun4v.o |
18 | obj-$(CONFIG_SMP) += smp.o trampoline.o | 18 | obj-$(CONFIG_SMP) += smp.o trampoline.o |
19 | obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o | 19 | obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o |
20 | obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o | 20 | obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o |
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 2ff7c32ab0ce..95ffa9418620 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -188,6 +188,7 @@ extern void psycho_init(int, char *); | |||
188 | extern void schizo_init(int, char *); | 188 | extern void schizo_init(int, char *); |
189 | extern void schizo_plus_init(int, char *); | 189 | extern void schizo_plus_init(int, char *); |
190 | extern void tomatillo_init(int, char *); | 190 | extern void tomatillo_init(int, char *); |
191 | extern void sun4v_pci_init(int, char *); | ||
191 | 192 | ||
192 | static struct { | 193 | static struct { |
193 | char *model_name; | 194 | char *model_name; |
@@ -204,6 +205,7 @@ static struct { | |||
204 | { "pci108e,8002", schizo_plus_init }, | 205 | { "pci108e,8002", schizo_plus_init }, |
205 | { "SUNW,tomatillo", tomatillo_init }, | 206 | { "SUNW,tomatillo", tomatillo_init }, |
206 | { "pci108e,a801", tomatillo_init }, | 207 | { "pci108e,a801", tomatillo_init }, |
208 | { "SUNW,sun4v-pci", sun4v_pci_init }, | ||
207 | }; | 209 | }; |
208 | #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ | 210 | #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \ |
209 | sizeof(pci_controller_table[0])) | 211 | sizeof(pci_controller_table[0])) |
@@ -283,6 +285,12 @@ int __init pcic_present(void) | |||
283 | return pci_controller_scan(pci_is_controller); | 285 | return pci_controller_scan(pci_is_controller); |
284 | } | 286 | } |
285 | 287 | ||
288 | struct pci_iommu_ops *pci_iommu_ops; | ||
289 | EXPORT_SYMBOL(pci_iommu_ops); | ||
290 | |||
291 | extern struct pci_iommu_ops pci_sun4u_iommu_ops, | ||
292 | pci_sun4v_iommu_ops; | ||
293 | |||
286 | /* Find each controller in the system, attach and initialize | 294 | /* Find each controller in the system, attach and initialize |
287 | * software state structure for each and link into the | 295 | * software state structure for each and link into the |
288 | * pci_controller_root. Setup the controller enough such | 296 | * pci_controller_root. Setup the controller enough such |
@@ -290,6 +298,11 @@ int __init pcic_present(void) | |||
290 | */ | 298 | */ |
291 | static void __init pci_controller_probe(void) | 299 | static void __init pci_controller_probe(void) |
292 | { | 300 | { |
301 | if (tlb_type == hypervisor) | ||
302 | pci_iommu_ops = &pci_sun4v_iommu_ops; | ||
303 | else | ||
304 | pci_iommu_ops = &pci_sun4u_iommu_ops; | ||
305 | |||
293 | printk("PCI: Probing for controllers.\n"); | 306 | printk("PCI: Probing for controllers.\n"); |
294 | 307 | ||
295 | pci_controller_scan(pci_controller_init); | 308 | pci_controller_scan(pci_controller_init); |
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index a11910be1013..8e52232f6f31 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c | |||
@@ -219,7 +219,7 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) | |||
219 | * DMA for PCI device PDEV. Return non-NULL cpu-side address if | 219 | * DMA for PCI device PDEV. Return non-NULL cpu-side address if |
220 | * successful and set *DMA_ADDRP to the PCI side dma address. | 220 | * successful and set *DMA_ADDRP to the PCI side dma address. |
221 | */ | 221 | */ |
222 | void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) | 222 | static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) |
223 | { | 223 | { |
224 | struct pcidev_cookie *pcp; | 224 | struct pcidev_cookie *pcp; |
225 | struct pci_iommu *iommu; | 225 | struct pci_iommu *iommu; |
@@ -267,7 +267,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad | |||
267 | } | 267 | } |
268 | 268 | ||
269 | /* Free and unmap a consistent DMA translation. */ | 269 | /* Free and unmap a consistent DMA translation. */ |
270 | void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) | 270 | static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) |
271 | { | 271 | { |
272 | struct pcidev_cookie *pcp; | 272 | struct pcidev_cookie *pcp; |
273 | struct pci_iommu *iommu; | 273 | struct pci_iommu *iommu; |
@@ -294,7 +294,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_ | |||
294 | /* Map a single buffer at PTR of SZ bytes for PCI DMA | 294 | /* Map a single buffer at PTR of SZ bytes for PCI DMA |
295 | * in streaming mode. | 295 | * in streaming mode. |
296 | */ | 296 | */ |
297 | dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) | 297 | static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) |
298 | { | 298 | { |
299 | struct pcidev_cookie *pcp; | 299 | struct pcidev_cookie *pcp; |
300 | struct pci_iommu *iommu; | 300 | struct pci_iommu *iommu; |
@@ -415,7 +415,7 @@ do_flush_sync: | |||
415 | } | 415 | } |
416 | 416 | ||
417 | /* Unmap a single streaming mode DMA translation. */ | 417 | /* Unmap a single streaming mode DMA translation. */ |
418 | void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) | 418 | static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) |
419 | { | 419 | { |
420 | struct pcidev_cookie *pcp; | 420 | struct pcidev_cookie *pcp; |
421 | struct pci_iommu *iommu; | 421 | struct pci_iommu *iommu; |
@@ -548,7 +548,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | |||
548 | * When making changes here, inspect the assembly output. I was having | 548 | * When making changes here, inspect the assembly output. I was having |
549 | * hard time to kepp this routine out of using stack slots for holding variables. | 549 | * hard time to kepp this routine out of using stack slots for holding variables. |
550 | */ | 550 | */ |
551 | int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | 551 | static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) |
552 | { | 552 | { |
553 | struct pcidev_cookie *pcp; | 553 | struct pcidev_cookie *pcp; |
554 | struct pci_iommu *iommu; | 554 | struct pci_iommu *iommu; |
@@ -635,7 +635,7 @@ bad_no_ctx: | |||
635 | } | 635 | } |
636 | 636 | ||
637 | /* Unmap a set of streaming mode DMA translations. */ | 637 | /* Unmap a set of streaming mode DMA translations. */ |
638 | void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | 638 | static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) |
639 | { | 639 | { |
640 | struct pcidev_cookie *pcp; | 640 | struct pcidev_cookie *pcp; |
641 | struct pci_iommu *iommu; | 641 | struct pci_iommu *iommu; |
@@ -695,7 +695,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, | |||
695 | /* Make physical memory consistent for a single | 695 | /* Make physical memory consistent for a single |
696 | * streaming mode DMA translation after a transfer. | 696 | * streaming mode DMA translation after a transfer. |
697 | */ | 697 | */ |
698 | void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) | 698 | static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) |
699 | { | 699 | { |
700 | struct pcidev_cookie *pcp; | 700 | struct pcidev_cookie *pcp; |
701 | struct pci_iommu *iommu; | 701 | struct pci_iommu *iommu; |
@@ -735,7 +735,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size | |||
735 | /* Make physical memory consistent for a set of streaming | 735 | /* Make physical memory consistent for a set of streaming |
736 | * mode DMA translations after a transfer. | 736 | * mode DMA translations after a transfer. |
737 | */ | 737 | */ |
738 | void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | 738 | static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) |
739 | { | 739 | { |
740 | struct pcidev_cookie *pcp; | 740 | struct pcidev_cookie *pcp; |
741 | struct pci_iommu *iommu; | 741 | struct pci_iommu *iommu; |
@@ -776,6 +776,17 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i | |||
776 | spin_unlock_irqrestore(&iommu->lock, flags); | 776 | spin_unlock_irqrestore(&iommu->lock, flags); |
777 | } | 777 | } |
778 | 778 | ||
779 | struct pci_iommu_ops pci_sun4u_iommu_ops = { | ||
780 | .alloc_consistent = pci_4u_alloc_consistent, | ||
781 | .free_consistent = pci_4u_free_consistent, | ||
782 | .map_single = pci_4u_map_single, | ||
783 | .unmap_single = pci_4u_unmap_single, | ||
784 | .map_sg = pci_4u_map_sg, | ||
785 | .unmap_sg = pci_4u_unmap_sg, | ||
786 | .dma_sync_single_for_cpu = pci_4u_dma_sync_single_for_cpu, | ||
787 | .dma_sync_sg_for_cpu = pci_4u_dma_sync_sg_for_cpu, | ||
788 | }; | ||
789 | |||
779 | static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) | 790 | static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit) |
780 | { | 791 | { |
781 | struct pci_dev *ali_isa_bridge; | 792 | struct pci_dev *ali_isa_bridge; |
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c new file mode 100644 index 000000000000..c1a077196c57 --- /dev/null +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* pci_sun4v.c: SUN4V specific PCI controller support. | ||
2 | * | ||
3 | * Copyright (C) 2006 David S. Miller (davem@davemloft.net) | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/pci.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | |||
13 | #include <asm/pbm.h> | ||
14 | #include <asm/iommu.h> | ||
15 | #include <asm/irq.h> | ||
16 | #include <asm/upa.h> | ||
17 | #include <asm/pstate.h> | ||
18 | #include <asm/oplib.h> | ||
19 | #include <asm/hypervisor.h> | ||
20 | |||
21 | #include "pci_impl.h" | ||
22 | #include "iommu_common.h" | ||
23 | |||
24 | static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) | ||
25 | { | ||
26 | return NULL; | ||
27 | } | ||
28 | |||
29 | static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma) | ||
30 | { | ||
31 | } | ||
32 | |||
33 | static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction) | ||
34 | { | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | ||
43 | { | ||
44 | return nelems; | ||
45 | } | ||
46 | |||
47 | static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | static void pci_4v_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction) | ||
52 | { | ||
53 | } | ||
54 | |||
55 | static void pci_4v_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) | ||
56 | { | ||
57 | } | ||
58 | |||
59 | struct pci_iommu_ops pci_sun4v_iommu_ops = { | ||
60 | .alloc_consistent = pci_4v_alloc_consistent, | ||
61 | .free_consistent = pci_4v_free_consistent, | ||
62 | .map_single = pci_4v_map_single, | ||
63 | .unmap_single = pci_4v_unmap_single, | ||
64 | .map_sg = pci_4v_map_sg, | ||
65 | .unmap_sg = pci_4v_unmap_sg, | ||
66 | .dma_sync_single_for_cpu = pci_4v_dma_sync_single_for_cpu, | ||
67 | .dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu, | ||
68 | }; | ||
69 | |||
70 | void sun4v_pci_init(int node, char *model_name) | ||
71 | { | ||
72 | prom_printf("sun4v_pci_init: Implement me.\n"); | ||
73 | prom_halt(); | ||
74 | } | ||