diff options
Diffstat (limited to 'arch/powerpc/platforms')
33 files changed, 592 insertions, 175 deletions
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 74f31177e47a..a9260e21451e 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig | |||
@@ -72,6 +72,7 @@ config WALNUT | |||
72 | default y | 72 | default y |
73 | select 405GP | 73 | select 405GP |
74 | select PCI | 74 | select PCI |
75 | select OF_RTC | ||
75 | help | 76 | help |
76 | This option enables support for the IBM PPC405GP evaluation board. | 77 | This option enables support for the IBM PPC405GP evaluation board. |
77 | 78 | ||
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c index 88b66444dfb2..0422590040db 100644 --- a/arch/powerpc/platforms/40x/virtex.c +++ b/arch/powerpc/platforms/40x/virtex.c | |||
@@ -37,7 +37,7 @@ static int __init virtex_probe(void) | |||
37 | { | 37 | { |
38 | unsigned long root = of_get_flat_dt_root(); | 38 | unsigned long root = of_get_flat_dt_root(); |
39 | 39 | ||
40 | if (!of_flat_dt_is_compatible(root, "xilinx,virtex")) | 40 | if (!of_flat_dt_is_compatible(root, "xlnx,virtex")) |
41 | return 0; | 41 | return 0; |
42 | 42 | ||
43 | return 1; | 43 | return 1; |
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c index 5d9edd917f92..b8b257efeb77 100644 --- a/arch/powerpc/platforms/40x/walnut.c +++ b/arch/powerpc/platforms/40x/walnut.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
21 | #include <linux/rtc.h> | ||
21 | 22 | ||
22 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
23 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 8f01563dbd2a..da5b7b7599db 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c | |||
@@ -137,7 +137,7 @@ static int __init pika_dtm_start(void) | |||
137 | } | 137 | } |
138 | of_node_put(np); | 138 | of_node_put(np); |
139 | 139 | ||
140 | fpga = ioremap(res.start + 0x20, 4); | 140 | fpga = ioremap(res.start, 0x24); |
141 | if (fpga == NULL) | 141 | if (fpga == NULL) |
142 | return -ENOENT; | 142 | return -ENOENT; |
143 | 143 | ||
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig new file mode 100644 index 000000000000..c6fa49e23dc0 --- /dev/null +++ b/arch/powerpc/platforms/512x/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | config PPC_MPC512x | ||
2 | bool | ||
3 | select FSL_SOC | ||
4 | select IPIC | ||
5 | default n | ||
6 | |||
7 | config PPC_MPC5121 | ||
8 | bool | ||
9 | select PPC_MPC512x | ||
10 | default n | ||
11 | |||
12 | config MPC5121_ADS | ||
13 | bool "Freescale MPC5121E ADS" | ||
14 | depends on PPC_MULTIPLATFORM && PPC32 | ||
15 | select DEFAULT_UIMAGE | ||
16 | select WANT_DEVICE_TREE | ||
17 | select PPC_MPC5121 | ||
18 | help | ||
19 | This option enables support for the MPC5121E ADS board. | ||
20 | default n | ||
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile new file mode 100644 index 000000000000..232c89f2039a --- /dev/null +++ b/arch/powerpc/platforms/512x/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # | ||
2 | # Makefile for the Freescale PowerPC 512x linux kernel. | ||
3 | # | ||
4 | obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o | ||
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads.c b/arch/powerpc/platforms/512x/mpc5121_ads.c new file mode 100644 index 000000000000..50bd3a319022 --- /dev/null +++ b/arch/powerpc/platforms/512x/mpc5121_ads.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved. | ||
3 | * | ||
4 | * Author: John Rigby, <jrigby@freescale.com>, Thur Mar 29 2007 | ||
5 | * | ||
6 | * Description: | ||
7 | * MPC5121 ADS board setup | ||
8 | * | ||
9 | * This is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | |||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/ipic.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/time.h> | ||
25 | |||
26 | /** | ||
27 | * mpc512x_find_ips_freq - Find the IPS bus frequency for a device | ||
28 | * @node: device node | ||
29 | * | ||
30 | * Returns IPS bus frequency, or 0 if the bus frequency cannot be found. | ||
31 | */ | ||
32 | unsigned long | ||
33 | mpc512x_find_ips_freq(struct device_node *node) | ||
34 | { | ||
35 | struct device_node *np; | ||
36 | const unsigned int *p_ips_freq = NULL; | ||
37 | |||
38 | of_node_get(node); | ||
39 | while (node) { | ||
40 | p_ips_freq = of_get_property(node, "bus-frequency", NULL); | ||
41 | if (p_ips_freq) | ||
42 | break; | ||
43 | |||
44 | np = of_get_parent(node); | ||
45 | of_node_put(node); | ||
46 | node = np; | ||
47 | } | ||
48 | if (node) | ||
49 | of_node_put(node); | ||
50 | |||
51 | return p_ips_freq ? *p_ips_freq : 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(mpc512x_find_ips_freq); | ||
54 | |||
55 | static struct of_device_id __initdata of_bus_ids[] = { | ||
56 | { .name = "soc", }, | ||
57 | { .name = "localbus", }, | ||
58 | {}, | ||
59 | }; | ||
60 | |||
61 | static void __init mpc5121_ads_declare_of_platform_devices(void) | ||
62 | { | ||
63 | /* Find every child of the SOC node and add it to of_platform */ | ||
64 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | ||
65 | printk(KERN_ERR __FILE__ ": " | ||
66 | "Error while probing of_platform bus\n"); | ||
67 | } | ||
68 | |||
69 | static void __init mpc5121_ads_init_IRQ(void) | ||
70 | { | ||
71 | struct device_node *np; | ||
72 | |||
73 | np = of_find_compatible_node(NULL, NULL, "fsl,ipic"); | ||
74 | if (!np) | ||
75 | return; | ||
76 | |||
77 | ipic_init(np, 0); | ||
78 | of_node_put(np); | ||
79 | |||
80 | /* | ||
81 | * Initialize the default interrupt mapping priorities, | ||
82 | * in case the boot rom changed something on us. | ||
83 | */ | ||
84 | ipic_set_default_priority(); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Called very early, MMU is off, device-tree isn't unflattened | ||
89 | */ | ||
90 | static int __init mpc5121_ads_probe(void) | ||
91 | { | ||
92 | unsigned long root = of_get_flat_dt_root(); | ||
93 | |||
94 | return of_flat_dt_is_compatible(root, "fsl,mpc5121ads"); | ||
95 | } | ||
96 | |||
97 | define_machine(mpc5121_ads) { | ||
98 | .name = "MPC5121 ADS", | ||
99 | .probe = mpc5121_ads_probe, | ||
100 | .init = mpc5121_ads_declare_of_platform_devices, | ||
101 | .init_IRQ = mpc5121_ads_init_IRQ, | ||
102 | .get_irq = ipic_get_irq, | ||
103 | .calibrate_decr = generic_calibrate_decr, | ||
104 | }; | ||
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c index 3fce6b375dbc..7d3018751988 100644 --- a/arch/powerpc/platforms/82xx/mpc8272_ads.c +++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c | |||
@@ -134,13 +134,12 @@ static void __init mpc8272_ads_setup_arch(void) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | bcsr = of_iomap(np, 0); | 136 | bcsr = of_iomap(np, 0); |
137 | of_node_put(np); | ||
137 | if (!bcsr) { | 138 | if (!bcsr) { |
138 | printk(KERN_ERR "Cannot map BCSR registers\n"); | 139 | printk(KERN_ERR "Cannot map BCSR registers\n"); |
139 | return; | 140 | return; |
140 | } | 141 | } |
141 | 142 | ||
142 | of_node_put(np); | ||
143 | |||
144 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); | 143 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); |
145 | setbits32(&bcsr[1], BCSR1_FETH_RST); | 144 | setbits32(&bcsr[1], BCSR1_FETH_RST); |
146 | 145 | ||
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c index 68196e349994..e1dceeec4994 100644 --- a/arch/powerpc/platforms/82xx/pq2fads.c +++ b/arch/powerpc/platforms/82xx/pq2fads.c | |||
@@ -130,13 +130,12 @@ static void __init pq2fads_setup_arch(void) | |||
130 | } | 130 | } |
131 | 131 | ||
132 | bcsr = of_iomap(np, 0); | 132 | bcsr = of_iomap(np, 0); |
133 | of_node_put(np); | ||
133 | if (!bcsr) { | 134 | if (!bcsr) { |
134 | printk(KERN_ERR "Cannot map BCSR registers\n"); | 135 | printk(KERN_ERR "Cannot map BCSR registers\n"); |
135 | return; | 136 | return; |
136 | } | 137 | } |
137 | 138 | ||
138 | of_node_put(np); | ||
139 | |||
140 | /* Enable the serial and ethernet ports */ | 139 | /* Enable the serial and ethernet ports */ |
141 | 140 | ||
142 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); | 141 | clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN); |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 9f0fd88b2b1f..e7f706b624fe 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
@@ -101,7 +101,7 @@ static void __init mpc832x_rdb_setup_arch(void) | |||
101 | #ifdef CONFIG_QUICC_ENGINE | 101 | #ifdef CONFIG_QUICC_ENGINE |
102 | qe_reset(); | 102 | qe_reset(); |
103 | 103 | ||
104 | if ((np = of_find_node_by_name(np, "par_io")) != NULL) { | 104 | if ((np = of_find_node_by_name(NULL, "par_io")) != NULL) { |
105 | par_io_init(np); | 105 | par_io_init(np); |
106 | of_node_put(np); | 106 | of_node_put(np); |
107 | 107 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index 88bb748aff0d..68065e62fc3d 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -14,6 +14,8 @@ | |||
14 | #define MPC83XX_SCCR_USB_DRCM_11 0x00300000 | 14 | #define MPC83XX_SCCR_USB_DRCM_11 0x00300000 |
15 | #define MPC83XX_SCCR_USB_DRCM_01 0x00100000 | 15 | #define MPC83XX_SCCR_USB_DRCM_01 0x00100000 |
16 | #define MPC83XX_SCCR_USB_DRCM_10 0x00200000 | 16 | #define MPC83XX_SCCR_USB_DRCM_10 0x00200000 |
17 | #define MPC8315_SCCR_USB_MASK 0x00c00000 | ||
18 | #define MPC8315_SCCR_USB_DRCM_11 0x00c00000 | ||
17 | #define MPC837X_SCCR_USB_DRCM_11 0x00c00000 | 19 | #define MPC837X_SCCR_USB_DRCM_11 0x00c00000 |
18 | 20 | ||
19 | /* system i/o configuration register low */ | 21 | /* system i/o configuration register low */ |
diff --git a/arch/powerpc/platforms/83xx/usb.c b/arch/powerpc/platforms/83xx/usb.c index 681230a30acd..471fdd8f4108 100644 --- a/arch/powerpc/platforms/83xx/usb.c +++ b/arch/powerpc/platforms/83xx/usb.c | |||
@@ -104,6 +104,7 @@ int mpc831x_usb_cfg(void) | |||
104 | u32 temp; | 104 | u32 temp; |
105 | void __iomem *immap, *usb_regs; | 105 | void __iomem *immap, *usb_regs; |
106 | struct device_node *np = NULL; | 106 | struct device_node *np = NULL; |
107 | struct device_node *immr_node = NULL; | ||
107 | const void *prop; | 108 | const void *prop; |
108 | struct resource res; | 109 | struct resource res; |
109 | int ret = 0; | 110 | int ret = 0; |
@@ -124,10 +125,15 @@ int mpc831x_usb_cfg(void) | |||
124 | } | 125 | } |
125 | 126 | ||
126 | /* Configure clock */ | 127 | /* Configure clock */ |
127 | temp = in_be32(immap + MPC83XX_SCCR_OFFS); | 128 | immr_node = of_get_parent(np); |
128 | temp &= ~MPC83XX_SCCR_USB_MASK; | 129 | if (immr_node && of_device_is_compatible(immr_node, "fsl,mpc8315-immr")) |
129 | temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ | 130 | clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, |
130 | out_be32(immap + MPC83XX_SCCR_OFFS, temp); | 131 | MPC8315_SCCR_USB_MASK, |
132 | MPC8315_SCCR_USB_DRCM_11); | ||
133 | else | ||
134 | clrsetbits_be32(immap + MPC83XX_SCCR_OFFS, | ||
135 | MPC83XX_SCCR_USB_MASK, | ||
136 | MPC83XX_SCCR_USB_DRCM_11); | ||
131 | 137 | ||
132 | /* Configure pin mux for ULPI. There is no pin mux for UTMI */ | 138 | /* Configure pin mux for ULPI. There is no pin mux for UTMI */ |
133 | if (prop && !strcmp(prop, "ulpi")) { | 139 | if (prop && !strcmp(prop, "ulpi")) { |
@@ -144,6 +150,9 @@ int mpc831x_usb_cfg(void) | |||
144 | 150 | ||
145 | iounmap(immap); | 151 | iounmap(immap); |
146 | 152 | ||
153 | if (immr_node) | ||
154 | of_node_put(immr_node); | ||
155 | |||
147 | /* Map USB SOC space */ | 156 | /* Map USB SOC space */ |
148 | ret = of_address_to_resource(np, 0, &res); | 157 | ret = of_address_to_resource(np, 0, &res); |
149 | if (ret) { | 158 | if (ret) { |
diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c index c6bc0783c3b0..82363e98f50e 100644 --- a/arch/powerpc/platforms/8xx/adder875.c +++ b/arch/powerpc/platforms/8xx/adder875.c | |||
@@ -15,12 +15,12 @@ | |||
15 | 15 | ||
16 | #include <asm/time.h> | 16 | #include <asm/time.h> |
17 | #include <asm/machdep.h> | 17 | #include <asm/machdep.h> |
18 | #include <asm/commproc.h> | 18 | #include <asm/cpm1.h> |
19 | #include <asm/fs_pd.h> | 19 | #include <asm/fs_pd.h> |
20 | #include <asm/udbg.h> | 20 | #include <asm/udbg.h> |
21 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
22 | 22 | ||
23 | #include <sysdev/commproc.h> | 23 | #include "mpc8xx.h" |
24 | 24 | ||
25 | struct cpm_pin { | 25 | struct cpm_pin { |
26 | int port, pin, flags; | 26 | int port, pin, flags; |
@@ -108,7 +108,7 @@ define_machine(adder875) { | |||
108 | .name = "Adder MPC875", | 108 | .name = "Adder MPC875", |
109 | .probe = adder875_probe, | 109 | .probe = adder875_probe, |
110 | .setup_arch = adder875_setup, | 110 | .setup_arch = adder875_setup, |
111 | .init_IRQ = m8xx_pic_init, | 111 | .init_IRQ = mpc8xx_pics_init, |
112 | .get_irq = mpc8xx_get_irq, | 112 | .get_irq = mpc8xx_get_irq, |
113 | .restart = mpc8xx_restart, | 113 | .restart = mpc8xx_restart, |
114 | .calibrate_decr = generic_calibrate_decr, | 114 | .calibrate_decr = generic_calibrate_decr, |
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c index a8dffa005775..7d9ac6040d63 100644 --- a/arch/powerpc/platforms/8xx/ep88xc.c +++ b/arch/powerpc/platforms/8xx/ep88xc.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <asm/machdep.h> | 15 | #include <asm/machdep.h> |
16 | #include <asm/io.h> | 16 | #include <asm/io.h> |
17 | #include <asm/udbg.h> | 17 | #include <asm/udbg.h> |
18 | #include <asm/commproc.h> | ||
19 | #include <asm/cpm1.h> | 18 | #include <asm/cpm1.h> |
20 | 19 | ||
21 | #include "mpc8xx.h" | 20 | #include "mpc8xx.h" |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index fdce10c4f074..fcedbec07f94 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -24,6 +24,7 @@ config PPC_83xx | |||
24 | select MPC83xx | 24 | select MPC83xx |
25 | select IPIC | 25 | select IPIC |
26 | select WANT_DEVICE_TREE | 26 | select WANT_DEVICE_TREE |
27 | select FSL_EMB_PERFMON | ||
27 | 28 | ||
28 | config PPC_86xx | 29 | config PPC_86xx |
29 | bool "Freescale 86xx" | 30 | bool "Freescale 86xx" |
@@ -41,6 +42,7 @@ config CLASSIC32 | |||
41 | source "arch/powerpc/platforms/pseries/Kconfig" | 42 | source "arch/powerpc/platforms/pseries/Kconfig" |
42 | source "arch/powerpc/platforms/iseries/Kconfig" | 43 | source "arch/powerpc/platforms/iseries/Kconfig" |
43 | source "arch/powerpc/platforms/chrp/Kconfig" | 44 | source "arch/powerpc/platforms/chrp/Kconfig" |
45 | source "arch/powerpc/platforms/512x/Kconfig" | ||
44 | source "arch/powerpc/platforms/52xx/Kconfig" | 46 | source "arch/powerpc/platforms/52xx/Kconfig" |
45 | source "arch/powerpc/platforms/powermac/Kconfig" | 47 | source "arch/powerpc/platforms/powermac/Kconfig" |
46 | source "arch/powerpc/platforms/prep/Kconfig" | 48 | source "arch/powerpc/platforms/prep/Kconfig" |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 7fc41104d53e..69941ba70975 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -14,7 +14,7 @@ choice | |||
14 | There are five families of 32 bit PowerPC chips supported. | 14 | There are five families of 32 bit PowerPC chips supported. |
15 | The most common ones are the desktop and server CPUs (601, 603, | 15 | The most common ones are the desktop and server CPUs (601, 603, |
16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their | 16 | 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their |
17 | embedded 52xx/82xx/83xx/86xx counterparts. | 17 | embedded 512x/52xx/82xx/83xx/86xx counterparts. |
18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 | 18 | The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 |
19 | (85xx) each form a family of their own that is not compatible | 19 | (85xx) each form a family of their own that is not compatible |
20 | with the others. | 20 | with the others. |
@@ -22,7 +22,7 @@ choice | |||
22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. | 22 | If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. |
23 | 23 | ||
24 | config 6xx | 24 | config 6xx |
25 | bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx" | 25 | bool "512x/52xx/6xx/7xx/74xx/82xx/83xx/86xx" |
26 | select PPC_FPU | 26 | select PPC_FPU |
27 | 27 | ||
28 | config PPC_85xx | 28 | config PPC_85xx |
@@ -94,6 +94,7 @@ config 8xx | |||
94 | bool | 94 | bool |
95 | 95 | ||
96 | config E500 | 96 | config E500 |
97 | select FSL_EMB_PERFMON | ||
97 | bool | 98 | bool |
98 | 99 | ||
99 | config PPC_FPU | 100 | config PPC_FPU |
@@ -115,6 +116,9 @@ config FSL_BOOKE | |||
115 | depends on E200 || E500 | 116 | depends on E200 || E500 |
116 | default y | 117 | default y |
117 | 118 | ||
119 | config FSL_EMB_PERFMON | ||
120 | bool | ||
121 | |||
118 | config PTE_64BIT | 122 | config PTE_64BIT |
119 | bool | 123 | bool |
120 | depends on 44x || E500 | 124 | depends on 44x || E500 |
@@ -221,7 +225,7 @@ config NR_CPUS | |||
221 | 225 | ||
222 | config NOT_COHERENT_CACHE | 226 | config NOT_COHERENT_CACHE |
223 | bool | 227 | bool |
224 | depends on 4xx || 8xx || E200 | 228 | depends on 4xx || 8xx || E200 || PPC_MPC512x |
225 | default y | 229 | default y |
226 | 230 | ||
227 | config CHECK_CACHE_COHERENCY | 231 | config CHECK_CACHE_COHERENCY |
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 6d9079da5f5a..a984894466d9 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
@@ -11,6 +11,7 @@ endif | |||
11 | obj-$(CONFIG_PPC_CHRP) += chrp/ | 11 | obj-$(CONFIG_PPC_CHRP) += chrp/ |
12 | obj-$(CONFIG_40x) += 40x/ | 12 | obj-$(CONFIG_40x) += 40x/ |
13 | obj-$(CONFIG_44x) += 44x/ | 13 | obj-$(CONFIG_44x) += 44x/ |
14 | obj-$(CONFIG_PPC_MPC512x) += 512x/ | ||
14 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ | 15 | obj-$(CONFIG_PPC_MPC52xx) += 52xx/ |
15 | obj-$(CONFIG_PPC_8xx) += 8xx/ | 16 | obj-$(CONFIG_PPC_8xx) += 8xx/ |
16 | obj-$(CONFIG_PPC_82xx) += 82xx/ | 17 | obj-$(CONFIG_PPC_82xx) += 82xx/ |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 3a963b4a9be0..2f169991896d 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -54,6 +54,13 @@ config SPU_FS_64K_LS | |||
54 | uses 4K pages. This can improve performances of applications | 54 | uses 4K pages. This can improve performances of applications |
55 | using multiple SPEs by lowering the TLB pressure on them. | 55 | using multiple SPEs by lowering the TLB pressure on them. |
56 | 56 | ||
57 | config SPU_TRACE | ||
58 | tristate "SPU event tracing support" | ||
59 | depends on SPU_FS && MARKERS | ||
60 | help | ||
61 | This option allows reading a trace of spu-related events through | ||
62 | the sputrace file in procfs. | ||
63 | |||
57 | config SPU_BASE | 64 | config SPU_BASE |
58 | bool | 65 | bool |
59 | default n | 66 | default n |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 095988f13bf4..d95e71dee91f 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/msi.h> | 15 | #include <linux/msi.h> |
16 | #include <linux/reboot.h> | 16 | #include <linux/of_platform.h> |
17 | 17 | ||
18 | #include <asm/dcr.h> | 18 | #include <asm/dcr.h> |
19 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
@@ -65,14 +65,12 @@ | |||
65 | 65 | ||
66 | struct axon_msic { | 66 | struct axon_msic { |
67 | struct irq_host *irq_host; | 67 | struct irq_host *irq_host; |
68 | __le32 *fifo; | 68 | __le32 *fifo_virt; |
69 | dma_addr_t fifo_phys; | ||
69 | dcr_host_t dcr_host; | 70 | dcr_host_t dcr_host; |
70 | struct list_head list; | ||
71 | u32 read_offset; | 71 | u32 read_offset; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static LIST_HEAD(axon_msic_list); | ||
75 | |||
76 | static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) | 74 | static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) |
77 | { | 75 | { |
78 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); | 76 | pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); |
@@ -94,7 +92,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) | |||
94 | 92 | ||
95 | while (msic->read_offset != write_offset) { | 93 | while (msic->read_offset != write_offset) { |
96 | idx = msic->read_offset / sizeof(__le32); | 94 | idx = msic->read_offset / sizeof(__le32); |
97 | msi = le32_to_cpu(msic->fifo[idx]); | 95 | msi = le32_to_cpu(msic->fifo_virt[idx]); |
98 | msi &= 0xFFFF; | 96 | msi &= 0xFFFF; |
99 | 97 | ||
100 | pr_debug("axon_msi: woff %x roff %x msi %x\n", | 98 | pr_debug("axon_msi: woff %x roff %x msi %x\n", |
@@ -139,6 +137,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev) | |||
139 | 137 | ||
140 | tmp = dn; | 138 | tmp = dn; |
141 | dn = of_find_node_by_phandle(*ph); | 139 | dn = of_find_node_by_phandle(*ph); |
140 | of_node_put(tmp); | ||
142 | if (!dn) { | 141 | if (!dn) { |
143 | dev_dbg(&dev->dev, | 142 | dev_dbg(&dev->dev, |
144 | "axon_msi: msi-translator doesn't point to a node\n"); | 143 | "axon_msi: msi-translator doesn't point to a node\n"); |
@@ -156,7 +155,6 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev) | |||
156 | 155 | ||
157 | out_error: | 156 | out_error: |
158 | of_node_put(dn); | 157 | of_node_put(dn); |
159 | of_node_put(tmp); | ||
160 | 158 | ||
161 | return msic; | 159 | return msic; |
162 | } | 160 | } |
@@ -292,30 +290,24 @@ static struct irq_host_ops msic_host_ops = { | |||
292 | .map = msic_host_map, | 290 | .map = msic_host_map, |
293 | }; | 291 | }; |
294 | 292 | ||
295 | static int axon_msi_notify_reboot(struct notifier_block *nb, | 293 | static int axon_msi_shutdown(struct of_device *device) |
296 | unsigned long code, void *data) | ||
297 | { | 294 | { |
298 | struct axon_msic *msic; | 295 | struct axon_msic *msic = device->dev.platform_data; |
299 | u32 tmp; | 296 | u32 tmp; |
300 | 297 | ||
301 | list_for_each_entry(msic, &axon_msic_list, list) { | 298 | pr_debug("axon_msi: disabling %s\n", |
302 | pr_debug("axon_msi: disabling %s\n", | 299 | msic->irq_host->of_node->full_name); |
303 | msic->irq_host->of_node->full_name); | 300 | tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); |
304 | tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); | 301 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; |
305 | tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; | 302 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); |
306 | msic_dcr_write(msic, MSIC_CTRL_REG, tmp); | ||
307 | } | ||
308 | 303 | ||
309 | return 0; | 304 | return 0; |
310 | } | 305 | } |
311 | 306 | ||
312 | static struct notifier_block axon_msi_reboot_notifier = { | 307 | static int axon_msi_probe(struct of_device *device, |
313 | .notifier_call = axon_msi_notify_reboot | 308 | const struct of_device_id *device_id) |
314 | }; | ||
315 | |||
316 | static int axon_msi_setup_one(struct device_node *dn) | ||
317 | { | 309 | { |
318 | struct page *page; | 310 | struct device_node *dn = device->node; |
319 | struct axon_msic *msic; | 311 | struct axon_msic *msic; |
320 | unsigned int virq; | 312 | unsigned int virq; |
321 | int dcr_base, dcr_len; | 313 | int dcr_base, dcr_len; |
@@ -346,16 +338,14 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
346 | goto out_free_msic; | 338 | goto out_free_msic; |
347 | } | 339 | } |
348 | 340 | ||
349 | page = alloc_pages_node(of_node_to_nid(dn), GFP_KERNEL, | 341 | msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, |
350 | get_order(MSIC_FIFO_SIZE_BYTES)); | 342 | &msic->fifo_phys, GFP_KERNEL); |
351 | if (!page) { | 343 | if (!msic->fifo_virt) { |
352 | printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n", | 344 | printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n", |
353 | dn->full_name); | 345 | dn->full_name); |
354 | goto out_free_msic; | 346 | goto out_free_msic; |
355 | } | 347 | } |
356 | 348 | ||
357 | msic->fifo = page_address(page); | ||
358 | |||
359 | msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, | 349 | msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, |
360 | NR_IRQS, &msic_host_ops, 0); | 350 | NR_IRQS, &msic_host_ops, 0); |
361 | if (!msic->irq_host) { | 351 | if (!msic->irq_host) { |
@@ -378,14 +368,18 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
378 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); | 368 | pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); |
379 | 369 | ||
380 | /* Enable the MSIC hardware */ | 370 | /* Enable the MSIC hardware */ |
381 | msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, (u64)msic->fifo >> 32); | 371 | msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32); |
382 | msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG, | 372 | msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG, |
383 | (u64)msic->fifo & 0xFFFFFFFF); | 373 | msic->fifo_phys & 0xFFFFFFFF); |
384 | msic_dcr_write(msic, MSIC_CTRL_REG, | 374 | msic_dcr_write(msic, MSIC_CTRL_REG, |
385 | MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE | | 375 | MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE | |
386 | MSIC_CTRL_FIFO_SIZE); | 376 | MSIC_CTRL_FIFO_SIZE); |
387 | 377 | ||
388 | list_add(&msic->list, &axon_msic_list); | 378 | device->dev.platform_data = msic; |
379 | |||
380 | ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; | ||
381 | ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; | ||
382 | ppc_md.msi_check_device = axon_msi_check_device; | ||
389 | 383 | ||
390 | printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name); | 384 | printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name); |
391 | 385 | ||
@@ -394,7 +388,8 @@ static int axon_msi_setup_one(struct device_node *dn) | |||
394 | out_free_host: | 388 | out_free_host: |
395 | kfree(msic->irq_host); | 389 | kfree(msic->irq_host); |
396 | out_free_fifo: | 390 | out_free_fifo: |
397 | __free_pages(virt_to_page(msic->fifo), get_order(MSIC_FIFO_SIZE_BYTES)); | 391 | dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt, |
392 | msic->fifo_phys); | ||
398 | out_free_msic: | 393 | out_free_msic: |
399 | kfree(msic); | 394 | kfree(msic); |
400 | out: | 395 | out: |
@@ -402,28 +397,24 @@ out: | |||
402 | return -1; | 397 | return -1; |
403 | } | 398 | } |
404 | 399 | ||
405 | static int axon_msi_init(void) | 400 | static const struct of_device_id axon_msi_device_id[] = { |
406 | { | 401 | { |
407 | struct device_node *dn; | 402 | .compatible = "ibm,axon-msic" |
408 | int found = 0; | 403 | }, |
409 | 404 | {} | |
410 | pr_debug("axon_msi: initialising ...\n"); | 405 | }; |
411 | |||
412 | for_each_compatible_node(dn, NULL, "ibm,axon-msic") { | ||
413 | if (axon_msi_setup_one(dn) == 0) | ||
414 | found++; | ||
415 | } | ||
416 | |||
417 | if (found) { | ||
418 | ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; | ||
419 | ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; | ||
420 | ppc_md.msi_check_device = axon_msi_check_device; | ||
421 | |||
422 | register_reboot_notifier(&axon_msi_reboot_notifier); | ||
423 | 406 | ||
424 | pr_debug("axon_msi: registered callbacks!\n"); | 407 | static struct of_platform_driver axon_msi_driver = { |
425 | } | 408 | .match_table = axon_msi_device_id, |
409 | .probe = axon_msi_probe, | ||
410 | .shutdown = axon_msi_shutdown, | ||
411 | .driver = { | ||
412 | .name = "axon-msi" | ||
413 | }, | ||
414 | }; | ||
426 | 415 | ||
427 | return 0; | 416 | static int __init axon_msi_init(void) |
417 | { | ||
418 | return of_register_platform_driver(&axon_msi_driver); | ||
428 | } | 419 | } |
429 | arch_initcall(axon_msi_init); | 420 | subsys_initcall(axon_msi_init); |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index e6534b519c9a..a7f609b3b876 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -98,7 +98,7 @@ static int __init cell_publish_devices(void) | |||
98 | } | 98 | } |
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | machine_device_initcall(cell, cell_publish_devices); | 101 | machine_subsys_initcall(cell, cell_publish_devices); |
102 | 102 | ||
103 | static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc) | 103 | static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc) |
104 | { | 104 | { |
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index d3a349fb42e5..99610a6361f2 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile | |||
@@ -4,6 +4,8 @@ spufs-y += inode.o file.o context.o syscalls.o coredump.o | |||
4 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o | 4 | spufs-y += sched.o backing_ops.o hw_ops.o run.o gang.o |
5 | spufs-y += switch.o fault.o lscsa_alloc.o | 5 | spufs-y += switch.o fault.o lscsa_alloc.o |
6 | 6 | ||
7 | obj-$(CONFIG_SPU_TRACE) += sputrace.o | ||
8 | |||
7 | # Rules to build switch.o with the help of SPU tool chain | 9 | # Rules to build switch.o with the help of SPU tool chain |
8 | SPU_CROSS := spu- | 10 | SPU_CROSS := spu- |
9 | SPU_CC := $(SPU_CROSS)gcc | 11 | SPU_CC := $(SPU_CROSS)gcc |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 3fcd06418b01..1018acd1746b 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
30 | #include <linux/ptrace.h> | 30 | #include <linux/ptrace.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <linux/marker.h> | ||
32 | 33 | ||
33 | #include <asm/io.h> | 34 | #include <asm/io.h> |
34 | #include <asm/semaphore.h> | 35 | #include <asm/semaphore.h> |
@@ -358,6 +359,8 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
358 | struct spu_context *ctx = vma->vm_file->private_data; | 359 | struct spu_context *ctx = vma->vm_file->private_data; |
359 | unsigned long area, offset = address - vma->vm_start; | 360 | unsigned long area, offset = address - vma->vm_start; |
360 | 361 | ||
362 | spu_context_nospu_trace(spufs_ps_nopfn__enter, ctx); | ||
363 | |||
361 | offset += vma->vm_pgoff << PAGE_SHIFT; | 364 | offset += vma->vm_pgoff << PAGE_SHIFT; |
362 | if (offset >= ps_size) | 365 | if (offset >= ps_size) |
363 | return NOPFN_SIGBUS; | 366 | return NOPFN_SIGBUS; |
@@ -375,11 +378,14 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma, | |||
375 | 378 | ||
376 | if (ctx->state == SPU_STATE_SAVED) { | 379 | if (ctx->state == SPU_STATE_SAVED) { |
377 | up_read(¤t->mm->mmap_sem); | 380 | up_read(¤t->mm->mmap_sem); |
381 | spu_context_nospu_trace(spufs_ps_nopfn__sleep, ctx); | ||
378 | spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); | 382 | spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); |
383 | spu_context_trace(spufs_ps_nopfn__wake, ctx, ctx->spu); | ||
379 | down_read(¤t->mm->mmap_sem); | 384 | down_read(¤t->mm->mmap_sem); |
380 | } else { | 385 | } else { |
381 | area = ctx->spu->problem_phys + ps_offs; | 386 | area = ctx->spu->problem_phys + ps_offs; |
382 | vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT); | 387 | vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT); |
388 | spu_context_trace(spufs_ps_nopfn__insert, ctx, ctx->spu); | ||
383 | } | 389 | } |
384 | 390 | ||
385 | spu_release(ctx); | 391 | spu_release(ctx); |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index c0e968a4c211..90784c029f25 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -322,7 +322,7 @@ static struct spu_context * | |||
322 | spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, | 322 | spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, |
323 | struct file *filp) | 323 | struct file *filp) |
324 | { | 324 | { |
325 | struct spu_context *tmp, *neighbor; | 325 | struct spu_context *tmp, *neighbor, *err; |
326 | int count, node; | 326 | int count, node; |
327 | int aff_supp; | 327 | int aff_supp; |
328 | 328 | ||
@@ -354,11 +354,15 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, | |||
354 | if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) && | 354 | if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) && |
355 | !list_is_last(&neighbor->aff_list, &gang->aff_list_head) && | 355 | !list_is_last(&neighbor->aff_list, &gang->aff_list_head) && |
356 | !list_entry(neighbor->aff_list.next, struct spu_context, | 356 | !list_entry(neighbor->aff_list.next, struct spu_context, |
357 | aff_list)->aff_head) | 357 | aff_list)->aff_head) { |
358 | return ERR_PTR(-EEXIST); | 358 | err = ERR_PTR(-EEXIST); |
359 | goto out_put_neighbor; | ||
360 | } | ||
359 | 361 | ||
360 | if (gang != neighbor->gang) | 362 | if (gang != neighbor->gang) { |
361 | return ERR_PTR(-EINVAL); | 363 | err = ERR_PTR(-EINVAL); |
364 | goto out_put_neighbor; | ||
365 | } | ||
362 | 366 | ||
363 | count = 1; | 367 | count = 1; |
364 | list_for_each_entry(tmp, &gang->aff_list_head, aff_list) | 368 | list_for_each_entry(tmp, &gang->aff_list_head, aff_list) |
@@ -372,11 +376,17 @@ spufs_assert_affinity(unsigned int flags, struct spu_gang *gang, | |||
372 | break; | 376 | break; |
373 | } | 377 | } |
374 | 378 | ||
375 | if (node == MAX_NUMNODES) | 379 | if (node == MAX_NUMNODES) { |
376 | return ERR_PTR(-EEXIST); | 380 | err = ERR_PTR(-EEXIST); |
381 | goto out_put_neighbor; | ||
382 | } | ||
377 | } | 383 | } |
378 | 384 | ||
379 | return neighbor; | 385 | return neighbor; |
386 | |||
387 | out_put_neighbor: | ||
388 | put_spu_context(neighbor); | ||
389 | return err; | ||
380 | } | 390 | } |
381 | 391 | ||
382 | static void | 392 | static void |
@@ -454,9 +464,12 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
454 | if (ret) | 464 | if (ret) |
455 | goto out_aff_unlock; | 465 | goto out_aff_unlock; |
456 | 466 | ||
457 | if (affinity) | 467 | if (affinity) { |
458 | spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx, | 468 | spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx, |
459 | neighbor); | 469 | neighbor); |
470 | if (neighbor) | ||
471 | put_spu_context(neighbor); | ||
472 | } | ||
460 | 473 | ||
461 | /* | 474 | /* |
462 | * get references for dget and mntget, will be released | 475 | * get references for dget and mntget, will be released |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index c01a09da1e56..b4814c740d8a 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -410,8 +410,11 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event) | |||
410 | * since we have TIF_SINGLESTEP set, thus the kernel will do | 410 | * since we have TIF_SINGLESTEP set, thus the kernel will do |
411 | * it upon return from the syscall anyawy | 411 | * it upon return from the syscall anyawy |
412 | */ | 412 | */ |
413 | if ((status & SPU_STATUS_STOPPED_BY_STOP) | 413 | if (unlikely(status & SPU_STATUS_SINGLE_STEP)) |
414 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { | 414 | ret = -ERESTARTSYS; |
415 | |||
416 | else if (unlikely((status & SPU_STATUS_STOPPED_BY_STOP) | ||
417 | && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff)) { | ||
415 | force_sig(SIGTRAP, current); | 418 | force_sig(SIGTRAP, current); |
416 | ret = -ERESTARTSYS; | 419 | ret = -ERESTARTSYS; |
417 | } | 420 | } |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 00d914232af1..5915343e2599 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/pid_namespace.h> | 39 | #include <linux/pid_namespace.h> |
40 | #include <linux/proc_fs.h> | 40 | #include <linux/proc_fs.h> |
41 | #include <linux/seq_file.h> | 41 | #include <linux/seq_file.h> |
42 | #include <linux/marker.h> | ||
42 | 43 | ||
43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
44 | #include <asm/mmu_context.h> | 45 | #include <asm/mmu_context.h> |
@@ -216,8 +217,8 @@ void do_notify_spus_active(void) | |||
216 | */ | 217 | */ |
217 | static void spu_bind_context(struct spu *spu, struct spu_context *ctx) | 218 | static void spu_bind_context(struct spu *spu, struct spu_context *ctx) |
218 | { | 219 | { |
219 | pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, | 220 | spu_context_trace(spu_bind_context__enter, ctx, spu); |
220 | spu->number, spu->node); | 221 | |
221 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); | 222 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); |
222 | 223 | ||
223 | if (ctx->flags & SPU_CREATE_NOSCHED) | 224 | if (ctx->flags & SPU_CREATE_NOSCHED) |
@@ -399,8 +400,8 @@ static int has_affinity(struct spu_context *ctx) | |||
399 | */ | 400 | */ |
400 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) | 401 | static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) |
401 | { | 402 | { |
402 | pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, | 403 | spu_context_trace(spu_unbind_context__enter, ctx, spu); |
403 | spu->pid, spu->number, spu->node); | 404 | |
404 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); | 405 | spuctx_switch_state(ctx, SPU_UTIL_SYSTEM); |
405 | 406 | ||
406 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) | 407 | if (spu->ctx->flags & SPU_CREATE_NOSCHED) |
@@ -528,6 +529,8 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
528 | struct spu *spu, *aff_ref_spu; | 529 | struct spu *spu, *aff_ref_spu; |
529 | int node, n; | 530 | int node, n; |
530 | 531 | ||
532 | spu_context_nospu_trace(spu_get_idle__enter, ctx); | ||
533 | |||
531 | if (ctx->gang) { | 534 | if (ctx->gang) { |
532 | mutex_lock(&ctx->gang->aff_mutex); | 535 | mutex_lock(&ctx->gang->aff_mutex); |
533 | if (has_affinity(ctx)) { | 536 | if (has_affinity(ctx)) { |
@@ -546,8 +549,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
546 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) | 549 | if (atomic_dec_and_test(&ctx->gang->aff_sched_count)) |
547 | ctx->gang->aff_ref_spu = NULL; | 550 | ctx->gang->aff_ref_spu = NULL; |
548 | mutex_unlock(&ctx->gang->aff_mutex); | 551 | mutex_unlock(&ctx->gang->aff_mutex); |
549 | 552 | goto not_found; | |
550 | return NULL; | ||
551 | } | 553 | } |
552 | mutex_unlock(&ctx->gang->aff_mutex); | 554 | mutex_unlock(&ctx->gang->aff_mutex); |
553 | } | 555 | } |
@@ -565,12 +567,14 @@ static struct spu *spu_get_idle(struct spu_context *ctx) | |||
565 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 567 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
566 | } | 568 | } |
567 | 569 | ||
570 | not_found: | ||
571 | spu_context_nospu_trace(spu_get_idle__not_found, ctx); | ||
568 | return NULL; | 572 | return NULL; |
569 | 573 | ||
570 | found: | 574 | found: |
571 | spu->alloc_state = SPU_USED; | 575 | spu->alloc_state = SPU_USED; |
572 | mutex_unlock(&cbe_spu_info[node].list_mutex); | 576 | mutex_unlock(&cbe_spu_info[node].list_mutex); |
573 | pr_debug("Got SPU %d %d\n", spu->number, spu->node); | 577 | spu_context_trace(spu_get_idle__found, ctx, spu); |
574 | spu_init_channels(spu); | 578 | spu_init_channels(spu); |
575 | return spu; | 579 | return spu; |
576 | } | 580 | } |
@@ -587,6 +591,8 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
587 | struct spu *spu; | 591 | struct spu *spu; |
588 | int node, n; | 592 | int node, n; |
589 | 593 | ||
594 | spu_context_nospu_trace(spu_find_vitim__enter, ctx); | ||
595 | |||
590 | /* | 596 | /* |
591 | * Look for a possible preemption candidate on the local node first. | 597 | * Look for a possible preemption candidate on the local node first. |
592 | * If there is no candidate look at the other nodes. This isn't | 598 | * If there is no candidate look at the other nodes. This isn't |
@@ -640,6 +646,8 @@ static struct spu *find_victim(struct spu_context *ctx) | |||
640 | goto restart; | 646 | goto restart; |
641 | } | 647 | } |
642 | 648 | ||
649 | spu_context_trace(__spu_deactivate__unload, ctx, spu); | ||
650 | |||
643 | mutex_lock(&cbe_spu_info[node].list_mutex); | 651 | mutex_lock(&cbe_spu_info[node].list_mutex); |
644 | cbe_spu_info[node].nr_active--; | 652 | cbe_spu_info[node].nr_active--; |
645 | spu_unbind_context(spu, victim); | 653 | spu_unbind_context(spu, victim); |
@@ -822,6 +830,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) | |||
822 | */ | 830 | */ |
823 | void spu_deactivate(struct spu_context *ctx) | 831 | void spu_deactivate(struct spu_context *ctx) |
824 | { | 832 | { |
833 | spu_context_nospu_trace(spu_deactivate__enter, ctx); | ||
825 | __spu_deactivate(ctx, 1, MAX_PRIO); | 834 | __spu_deactivate(ctx, 1, MAX_PRIO); |
826 | } | 835 | } |
827 | 836 | ||
@@ -835,6 +844,7 @@ void spu_deactivate(struct spu_context *ctx) | |||
835 | */ | 844 | */ |
836 | void spu_yield(struct spu_context *ctx) | 845 | void spu_yield(struct spu_context *ctx) |
837 | { | 846 | { |
847 | spu_context_nospu_trace(spu_yield__enter, ctx); | ||
838 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { | 848 | if (!(ctx->flags & SPU_CREATE_NOSCHED)) { |
839 | mutex_lock(&ctx->state_mutex); | 849 | mutex_lock(&ctx->state_mutex); |
840 | __spu_deactivate(ctx, 0, MAX_PRIO); | 850 | __spu_deactivate(ctx, 0, MAX_PRIO); |
@@ -864,11 +874,15 @@ static noinline void spusched_tick(struct spu_context *ctx) | |||
864 | goto out; | 874 | goto out; |
865 | 875 | ||
866 | spu = ctx->spu; | 876 | spu = ctx->spu; |
877 | |||
878 | spu_context_trace(spusched_tick__preempt, ctx, spu); | ||
879 | |||
867 | new = grab_runnable_context(ctx->prio + 1, spu->node); | 880 | new = grab_runnable_context(ctx->prio + 1, spu->node); |
868 | if (new) { | 881 | if (new) { |
869 | spu_unschedule(spu, ctx); | 882 | spu_unschedule(spu, ctx); |
870 | spu_add_to_rq(ctx); | 883 | spu_add_to_rq(ctx); |
871 | } else { | 884 | } else { |
885 | spu_context_nospu_trace(spusched_tick__newslice, ctx); | ||
872 | ctx->time_slice++; | 886 | ctx->time_slice++; |
873 | } | 887 | } |
874 | out: | 888 | out: |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 0e114038ea6f..795a1b52538b 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -325,4 +325,9 @@ extern void spu_free_lscsa(struct spu_state *csa); | |||
325 | extern void spuctx_switch_state(struct spu_context *ctx, | 325 | extern void spuctx_switch_state(struct spu_context *ctx, |
326 | enum spu_utilization_state new_state); | 326 | enum spu_utilization_state new_state); |
327 | 327 | ||
328 | #define spu_context_trace(name, ctx, spu) \ | ||
329 | trace_mark(name, "%p %p", ctx, spu); | ||
330 | #define spu_context_nospu_trace(name, ctx) \ | ||
331 | trace_mark(name, "%p", ctx); | ||
332 | |||
328 | #endif | 333 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c new file mode 100644 index 000000000000..2b1953f6f12e --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/sputrace.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 IBM Deutschland Entwicklung GmbH | ||
3 | * Released under GPL v2. | ||
4 | * | ||
5 | * Partially based on net/ipv4/tcp_probe.c. | ||
6 | * | ||
7 | * Simple tracing facility for spu contexts. | ||
8 | */ | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/marker.h> | ||
13 | #include <linux/proc_fs.h> | ||
14 | #include <linux/wait.h> | ||
15 | #include <asm/atomic.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include "spufs.h" | ||
18 | |||
19 | struct spu_probe { | ||
20 | const char *name; | ||
21 | const char *format; | ||
22 | marker_probe_func *probe_func; | ||
23 | }; | ||
24 | |||
25 | struct sputrace { | ||
26 | ktime_t tstamp; | ||
27 | int owner_tid; /* owner */ | ||
28 | int curr_tid; | ||
29 | const char *name; | ||
30 | int number; | ||
31 | }; | ||
32 | |||
33 | static int bufsize __read_mostly = 16384; | ||
34 | MODULE_PARM_DESC(bufsize, "Log buffer size (number of records)"); | ||
35 | module_param(bufsize, int, 0); | ||
36 | |||
37 | |||
38 | static DEFINE_SPINLOCK(sputrace_lock); | ||
39 | static DECLARE_WAIT_QUEUE_HEAD(sputrace_wait); | ||
40 | static ktime_t sputrace_start; | ||
41 | static unsigned long sputrace_head, sputrace_tail; | ||
42 | static struct sputrace *sputrace_log; | ||
43 | |||
44 | static int sputrace_used(void) | ||
45 | { | ||
46 | return (sputrace_head - sputrace_tail) % bufsize; | ||
47 | } | ||
48 | |||
49 | static inline int sputrace_avail(void) | ||
50 | { | ||
51 | return bufsize - sputrace_used(); | ||
52 | } | ||
53 | |||
54 | static int sputrace_sprint(char *tbuf, int n) | ||
55 | { | ||
56 | const struct sputrace *t = sputrace_log + sputrace_tail % bufsize; | ||
57 | struct timespec tv = | ||
58 | ktime_to_timespec(ktime_sub(t->tstamp, sputrace_start)); | ||
59 | |||
60 | return snprintf(tbuf, n, | ||
61 | "[%lu.%09lu] %d: %s (thread = %d, spu = %d)\n", | ||
62 | (unsigned long) tv.tv_sec, | ||
63 | (unsigned long) tv.tv_nsec, | ||
64 | t->owner_tid, | ||
65 | t->name, | ||
66 | t->curr_tid, | ||
67 | t->number); | ||
68 | } | ||
69 | |||
70 | static ssize_t sputrace_read(struct file *file, char __user *buf, | ||
71 | size_t len, loff_t *ppos) | ||
72 | { | ||
73 | int error = 0, cnt = 0; | ||
74 | |||
75 | if (!buf || len < 0) | ||
76 | return -EINVAL; | ||
77 | |||
78 | while (cnt < len) { | ||
79 | char tbuf[128]; | ||
80 | int width; | ||
81 | |||
82 | error = wait_event_interruptible(sputrace_wait, | ||
83 | sputrace_used() > 0); | ||
84 | if (error) | ||
85 | break; | ||
86 | |||
87 | spin_lock(&sputrace_lock); | ||
88 | if (sputrace_head == sputrace_tail) { | ||
89 | spin_unlock(&sputrace_lock); | ||
90 | continue; | ||
91 | } | ||
92 | |||
93 | width = sputrace_sprint(tbuf, sizeof(tbuf)); | ||
94 | if (width < len) | ||
95 | sputrace_tail = (sputrace_tail + 1) % bufsize; | ||
96 | spin_unlock(&sputrace_lock); | ||
97 | |||
98 | if (width >= len) | ||
99 | break; | ||
100 | |||
101 | error = copy_to_user(buf + cnt, tbuf, width); | ||
102 | if (error) | ||
103 | break; | ||
104 | cnt += width; | ||
105 | } | ||
106 | |||
107 | return cnt == 0 ? error : cnt; | ||
108 | } | ||
109 | |||
110 | static int sputrace_open(struct inode *inode, struct file *file) | ||
111 | { | ||
112 | spin_lock(&sputrace_lock); | ||
113 | sputrace_head = sputrace_tail = 0; | ||
114 | sputrace_start = ktime_get(); | ||
115 | spin_unlock(&sputrace_lock); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static const struct file_operations sputrace_fops = { | ||
121 | .owner = THIS_MODULE, | ||
122 | .open = sputrace_open, | ||
123 | .read = sputrace_read, | ||
124 | }; | ||
125 | |||
126 | static void sputrace_log_item(const char *name, struct spu_context *ctx, | ||
127 | struct spu *spu) | ||
128 | { | ||
129 | spin_lock(&sputrace_lock); | ||
130 | if (sputrace_avail() > 1) { | ||
131 | struct sputrace *t = sputrace_log + sputrace_head; | ||
132 | |||
133 | t->tstamp = ktime_get(); | ||
134 | t->owner_tid = ctx->tid; | ||
135 | t->name = name; | ||
136 | t->curr_tid = current->pid; | ||
137 | t->number = spu ? spu->number : -1; | ||
138 | |||
139 | sputrace_head = (sputrace_head + 1) % bufsize; | ||
140 | } else { | ||
141 | printk(KERN_WARNING | ||
142 | "sputrace: lost samples due to full buffer.\n"); | ||
143 | } | ||
144 | spin_unlock(&sputrace_lock); | ||
145 | |||
146 | wake_up(&sputrace_wait); | ||
147 | } | ||
148 | |||
149 | static void spu_context_event(const struct marker *mdata, | ||
150 | void *private, const char *format, ...) | ||
151 | { | ||
152 | struct spu_probe *p = mdata->private; | ||
153 | va_list ap; | ||
154 | struct spu_context *ctx; | ||
155 | struct spu *spu; | ||
156 | |||
157 | va_start(ap, format); | ||
158 | ctx = va_arg(ap, struct spu_context *); | ||
159 | spu = va_arg(ap, struct spu *); | ||
160 | |||
161 | sputrace_log_item(p->name, ctx, spu); | ||
162 | va_end(ap); | ||
163 | } | ||
164 | |||
165 | static void spu_context_nospu_event(const struct marker *mdata, | ||
166 | void *private, const char *format, ...) | ||
167 | { | ||
168 | struct spu_probe *p = mdata->private; | ||
169 | va_list ap; | ||
170 | struct spu_context *ctx; | ||
171 | |||
172 | va_start(ap, format); | ||
173 | ctx = va_arg(ap, struct spu_context *); | ||
174 | |||
175 | sputrace_log_item(p->name, ctx, NULL); | ||
176 | va_end(ap); | ||
177 | } | ||
178 | |||
179 | struct spu_probe spu_probes[] = { | ||
180 | { "spu_bind_context__enter", "%p %p", spu_context_event }, | ||
181 | { "spu_unbind_context__enter", "%p %p", spu_context_event }, | ||
182 | { "spu_get_idle__enter", "%p", spu_context_nospu_event }, | ||
183 | { "spu_get_idle__found", "%p %p", spu_context_event }, | ||
184 | { "spu_get_idle__not_found", "%p", spu_context_nospu_event }, | ||
185 | { "spu_find_victim__enter", "%p", spu_context_nospu_event }, | ||
186 | { "spusched_tick__preempt", "%p %p", spu_context_event }, | ||
187 | { "spusched_tick__newslice", "%p", spu_context_nospu_event }, | ||
188 | { "spu_yield__enter", "%p", spu_context_nospu_event }, | ||
189 | { "spu_deactivate__enter", "%p", spu_context_nospu_event }, | ||
190 | { "__spu_deactivate__unload", "%p %p", spu_context_event }, | ||
191 | { "spufs_ps_nopfn__enter", "%p", spu_context_nospu_event }, | ||
192 | { "spufs_ps_nopfn__sleep", "%p", spu_context_nospu_event }, | ||
193 | { "spufs_ps_nopfn__wake", "%p %p", spu_context_event }, | ||
194 | { "spufs_ps_nopfn__insert", "%p %p", spu_context_event }, | ||
195 | { "spu_acquire_saved__enter", "%p", spu_context_nospu_event }, | ||
196 | { "destroy_spu_context__enter", "%p", spu_context_nospu_event }, | ||
197 | }; | ||
198 | |||
199 | static int __init sputrace_init(void) | ||
200 | { | ||
201 | struct proc_dir_entry *entry; | ||
202 | int i, error = -ENOMEM; | ||
203 | |||
204 | sputrace_log = kcalloc(sizeof(struct sputrace), | ||
205 | bufsize, GFP_KERNEL); | ||
206 | if (!sputrace_log) | ||
207 | goto out; | ||
208 | |||
209 | entry = create_proc_entry("sputrace", S_IRUSR, NULL); | ||
210 | if (!entry) | ||
211 | goto out_free_log; | ||
212 | entry->proc_fops = &sputrace_fops; | ||
213 | |||
214 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) { | ||
215 | struct spu_probe *p = &spu_probes[i]; | ||
216 | |||
217 | error = marker_probe_register(p->name, p->format, | ||
218 | p->probe_func, p); | ||
219 | if (error) | ||
220 | printk(KERN_INFO "Unable to register probe %s\n", | ||
221 | p->name); | ||
222 | |||
223 | error = marker_arm(p->name); | ||
224 | if (error) | ||
225 | printk(KERN_INFO "Unable to arm probe %s\n", p->name); | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | |||
230 | out_free_log: | ||
231 | kfree(sputrace_log); | ||
232 | out: | ||
233 | return -ENOMEM; | ||
234 | } | ||
235 | |||
236 | static void __exit sputrace_exit(void) | ||
237 | { | ||
238 | int i; | ||
239 | |||
240 | for (i = 0; i < ARRAY_SIZE(spu_probes); i++) | ||
241 | marker_probe_unregister(spu_probes[i].name); | ||
242 | |||
243 | remove_proc_entry("sputrace", NULL); | ||
244 | kfree(sputrace_log); | ||
245 | } | ||
246 | |||
247 | module_init(sputrace_init); | ||
248 | module_exit(sputrace_exit); | ||
249 | |||
250 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/powerpc/platforms/embedded6xx/storcenter.c b/arch/powerpc/platforms/embedded6xx/storcenter.c index e12e9d298716..8864e4884980 100644 --- a/arch/powerpc/platforms/embedded6xx/storcenter.c +++ b/arch/powerpc/platforms/embedded6xx/storcenter.c | |||
@@ -132,33 +132,18 @@ static void __init storcenter_init_IRQ(void) | |||
132 | 132 | ||
133 | paddr = (phys_addr_t)of_translate_address(dnp, prop); | 133 | paddr = (phys_addr_t)of_translate_address(dnp, prop); |
134 | mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, | 134 | mpic = mpic_alloc(dnp, paddr, MPIC_PRIMARY | MPIC_WANTS_RESET, |
135 | 4, 32, " EPIC "); | 135 | 16, 32, " OpenPIC "); |
136 | 136 | ||
137 | of_node_put(dnp); | 137 | of_node_put(dnp); |
138 | 138 | ||
139 | BUG_ON(mpic == NULL); | 139 | BUG_ON(mpic == NULL); |
140 | 140 | ||
141 | /* PCI IRQs */ | ||
142 | /* | 141 | /* |
143 | * 2.6.12 patch: | 142 | * 16 Serial Interrupts followed by 16 Internal Interrupts. |
144 | * openpic_set_sources(0, 5, OpenPIC_Addr + 0x10200); | 143 | * I2C is the second internal, so it is at 17, 0x11020. |
145 | * openpic_set_sources(5, 2, OpenPIC_Addr + 0x11120); | ||
146 | * first_irq, num_irqs, __iomem first_ISR | ||
147 | * o_ss: i, src: 0, fdf50200 | ||
148 | * o_ss: i, src: 1, fdf50220 | ||
149 | * o_ss: i, src: 2, fdf50240 | ||
150 | * o_ss: i, src: 3, fdf50260 | ||
151 | * o_ss: i, src: 4, fdf50280 | ||
152 | * o_ss: i, src: 5, fdf51120 | ||
153 | * o_ss: i, src: 6, fdf51140 | ||
154 | */ | 144 | */ |
155 | mpic_assign_isu(mpic, 0, paddr + 0x10200); | 145 | mpic_assign_isu(mpic, 0, paddr + 0x10200); |
156 | mpic_assign_isu(mpic, 1, paddr + 0x10220); | 146 | mpic_assign_isu(mpic, 1, paddr + 0x11000); |
157 | mpic_assign_isu(mpic, 2, paddr + 0x10240); | ||
158 | mpic_assign_isu(mpic, 3, paddr + 0x10260); | ||
159 | mpic_assign_isu(mpic, 4, paddr + 0x10280); | ||
160 | mpic_assign_isu(mpic, 5, paddr + 0x11120); | ||
161 | mpic_assign_isu(mpic, 6, paddr + 0x11140); | ||
162 | 147 | ||
163 | mpic_init(mpic); | 148 | mpic_init(mpic); |
164 | } | 149 | } |
@@ -178,7 +163,7 @@ static int __init storcenter_probe(void) | |||
178 | { | 163 | { |
179 | unsigned long root = of_get_flat_dt_root(); | 164 | unsigned long root = of_get_flat_dt_root(); |
180 | 165 | ||
181 | return of_flat_dt_is_compatible(root, "storcenter"); | 166 | return of_flat_dt_is_compatible(root, "iomega,storcenter"); |
182 | } | 167 | } |
183 | 168 | ||
184 | define_machine(storcenter){ | 169 | define_machine(storcenter){ |
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index c4ad54e0f288..1f032483c026 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
@@ -58,7 +58,7 @@ static void pseries_mach_cpu_die(void) | |||
58 | { | 58 | { |
59 | local_irq_disable(); | 59 | local_irq_disable(); |
60 | idle_task_exit(); | 60 | idle_task_exit(); |
61 | xics_teardown_cpu(0); | 61 | xics_teardown_cpu(); |
62 | unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow())); | 62 | unregister_slb_shadow(hard_smp_processor_id(), __pa(get_slb_shadow())); |
63 | rtas_stop_self(); | 63 | rtas_stop_self(); |
64 | /* Should never get here... */ | 64 | /* Should never get here... */ |
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c index 412a5e7aff2d..e9dd5fe081c9 100644 --- a/arch/powerpc/platforms/pseries/kexec.c +++ b/arch/powerpc/platforms/pseries/kexec.c | |||
@@ -54,7 +54,7 @@ void __init setup_kexec_cpu_down_mpic(void) | |||
54 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | 54 | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) |
55 | { | 55 | { |
56 | pseries_kexec_cpu_down(crash_shutdown, secondary); | 56 | pseries_kexec_cpu_down(crash_shutdown, secondary); |
57 | xics_teardown_cpu(secondary); | 57 | xics_kexec_teardown_cpu(secondary); |
58 | } | 58 | } |
59 | 59 | ||
60 | void __init setup_kexec_cpu_down_xics(void) | 60 | void __init setup_kexec_cpu_down_xics(void) |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index c02f8742c54d..2800fced8c7c 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -167,6 +167,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) | |||
167 | 167 | ||
168 | if ((child = of_get_next_child(np, NULL))) { | 168 | if ((child = of_get_next_child(np, NULL))) { |
169 | of_node_put(child); | 169 | of_node_put(child); |
170 | of_node_put(parent); | ||
170 | return -EBUSY; | 171 | return -EBUSY; |
171 | } | 172 | } |
172 | 173 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 8f8dd9c3ca6b..ca52b587166d 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -160,6 +160,46 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) | |||
160 | 160 | ||
161 | /* High level handlers and init code */ | 161 | /* High level handlers and init code */ |
162 | 162 | ||
163 | static void xics_update_irq_servers(void) | ||
164 | { | ||
165 | int i, j; | ||
166 | struct device_node *np; | ||
167 | u32 ilen; | ||
168 | const u32 *ireg, *isize; | ||
169 | u32 hcpuid; | ||
170 | |||
171 | /* Find the server numbers for the boot cpu. */ | ||
172 | np = of_get_cpu_node(boot_cpuid, NULL); | ||
173 | BUG_ON(!np); | ||
174 | |||
175 | ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); | ||
176 | if (!ireg) { | ||
177 | of_node_put(np); | ||
178 | return; | ||
179 | } | ||
180 | |||
181 | i = ilen / sizeof(int); | ||
182 | hcpuid = get_hard_smp_processor_id(boot_cpuid); | ||
183 | |||
184 | /* Global interrupt distribution server is specified in the last | ||
185 | * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last | ||
186 | * entry fom this property for current boot cpu id and use it as | ||
187 | * default distribution server | ||
188 | */ | ||
189 | for (j = 0; j < i; j += 2) { | ||
190 | if (ireg[j] == hcpuid) { | ||
191 | default_server = hcpuid; | ||
192 | default_distrib_server = ireg[j+1]; | ||
193 | |||
194 | isize = of_get_property(np, | ||
195 | "ibm,interrupt-server#-size", NULL); | ||
196 | if (isize) | ||
197 | interrupt_server_size = *isize; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | of_node_put(np); | ||
202 | } | ||
163 | 203 | ||
164 | #ifdef CONFIG_SMP | 204 | #ifdef CONFIG_SMP |
165 | static int get_irq_server(unsigned int virq, unsigned int strict_check) | 205 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
@@ -169,6 +209,9 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check) | |||
169 | cpumask_t cpumask = irq_desc[virq].affinity; | 209 | cpumask_t cpumask = irq_desc[virq].affinity; |
170 | cpumask_t tmp = CPU_MASK_NONE; | 210 | cpumask_t tmp = CPU_MASK_NONE; |
171 | 211 | ||
212 | if (! cpu_isset(default_server, cpu_online_map)) | ||
213 | xics_update_irq_servers(); | ||
214 | |||
172 | if (!distribute_irqs) | 215 | if (!distribute_irqs) |
173 | return default_server; | 216 | return default_server; |
174 | 217 | ||
@@ -658,39 +701,11 @@ static void __init xics_setup_8259_cascade(void) | |||
658 | set_irq_chained_handler(cascade, pseries_8259_cascade); | 701 | set_irq_chained_handler(cascade, pseries_8259_cascade); |
659 | } | 702 | } |
660 | 703 | ||
661 | static struct device_node *cpuid_to_of_node(int cpu) | ||
662 | { | ||
663 | struct device_node *np; | ||
664 | u32 hcpuid = get_hard_smp_processor_id(cpu); | ||
665 | |||
666 | for_each_node_by_type(np, "cpu") { | ||
667 | int i, len; | ||
668 | const u32 *intserv; | ||
669 | |||
670 | intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", | ||
671 | &len); | ||
672 | |||
673 | if (!intserv) | ||
674 | intserv = of_get_property(np, "reg", &len); | ||
675 | |||
676 | i = len / sizeof(u32); | ||
677 | |||
678 | while (i--) | ||
679 | if (intserv[i] == hcpuid) | ||
680 | return np; | ||
681 | } | ||
682 | |||
683 | return NULL; | ||
684 | } | ||
685 | |||
686 | void __init xics_init_IRQ(void) | 704 | void __init xics_init_IRQ(void) |
687 | { | 705 | { |
688 | int i, j; | ||
689 | struct device_node *np; | 706 | struct device_node *np; |
690 | u32 ilen, indx = 0; | 707 | u32 indx = 0; |
691 | const u32 *ireg, *isize; | ||
692 | int found = 0; | 708 | int found = 0; |
693 | u32 hcpuid; | ||
694 | 709 | ||
695 | ppc64_boot_msg(0x20, "XICS Init"); | 710 | ppc64_boot_msg(0x20, "XICS Init"); |
696 | 711 | ||
@@ -709,34 +724,7 @@ void __init xics_init_IRQ(void) | |||
709 | return; | 724 | return; |
710 | 725 | ||
711 | xics_init_host(); | 726 | xics_init_host(); |
712 | 727 | xics_update_irq_servers(); | |
713 | /* Find the server numbers for the boot cpu. */ | ||
714 | np = cpuid_to_of_node(boot_cpuid); | ||
715 | BUG_ON(!np); | ||
716 | ireg = of_get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); | ||
717 | if (!ireg) | ||
718 | goto skip_gserver_check; | ||
719 | i = ilen / sizeof(int); | ||
720 | hcpuid = get_hard_smp_processor_id(boot_cpuid); | ||
721 | |||
722 | /* Global interrupt distribution server is specified in the last | ||
723 | * entry of "ibm,ppc-interrupt-gserver#s" property. Get the last | ||
724 | * entry fom this property for current boot cpu id and use it as | ||
725 | * default distribution server | ||
726 | */ | ||
727 | for (j = 0; j < i; j += 2) { | ||
728 | if (ireg[j] == hcpuid) { | ||
729 | default_server = hcpuid; | ||
730 | default_distrib_server = ireg[j+1]; | ||
731 | |||
732 | isize = of_get_property(np, | ||
733 | "ibm,interrupt-server#-size", NULL); | ||
734 | if (isize) | ||
735 | interrupt_server_size = *isize; | ||
736 | } | ||
737 | } | ||
738 | skip_gserver_check: | ||
739 | of_node_put(np); | ||
740 | 728 | ||
741 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 729 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
742 | ppc_md.get_irq = xics_get_irq_lpar; | 730 | ppc_md.get_irq = xics_get_irq_lpar; |
@@ -775,11 +763,9 @@ void xics_request_IPIs(void) | |||
775 | } | 763 | } |
776 | #endif /* CONFIG_SMP */ | 764 | #endif /* CONFIG_SMP */ |
777 | 765 | ||
778 | void xics_teardown_cpu(int secondary) | 766 | void xics_teardown_cpu() |
779 | { | 767 | { |
780 | int cpu = smp_processor_id(); | 768 | int cpu = smp_processor_id(); |
781 | unsigned int ipi; | ||
782 | struct irq_desc *desc; | ||
783 | 769 | ||
784 | xics_set_cpu_priority(0); | 770 | xics_set_cpu_priority(0); |
785 | 771 | ||
@@ -790,9 +776,17 @@ void xics_teardown_cpu(int secondary) | |||
790 | lpar_qirr_info(cpu, 0xff); | 776 | lpar_qirr_info(cpu, 0xff); |
791 | else | 777 | else |
792 | direct_qirr_info(cpu, 0xff); | 778 | direct_qirr_info(cpu, 0xff); |
779 | } | ||
780 | |||
781 | void xics_kexec_teardown_cpu(int secondary) | ||
782 | { | ||
783 | unsigned int ipi; | ||
784 | struct irq_desc *desc; | ||
785 | |||
786 | xics_teardown_cpu(); | ||
793 | 787 | ||
794 | /* | 788 | /* |
795 | * we need to EOI the IPI if we got here from kexec down IPI | 789 | * we need to EOI the IPI |
796 | * | 790 | * |
797 | * probably need to check all the other interrupts too | 791 | * probably need to check all the other interrupts too |
798 | * should we be flagging idle loop instead? | 792 | * should we be flagging idle loop instead? |
@@ -880,8 +874,8 @@ void xics_migrate_irqs_away(void) | |||
880 | virq, cpu); | 874 | virq, cpu); |
881 | 875 | ||
882 | /* Reset affinity to all cpus */ | 876 | /* Reset affinity to all cpus */ |
877 | irq_desc[virq].affinity = CPU_MASK_ALL; | ||
883 | desc->chip->set_affinity(virq, CPU_MASK_ALL); | 878 | desc->chip->set_affinity(virq, CPU_MASK_ALL); |
884 | irq_desc[irq].affinity = CPU_MASK_ALL; | ||
885 | unlock: | 879 | unlock: |
886 | spin_unlock_irqrestore(&desc->lock, flags); | 880 | spin_unlock_irqrestore(&desc->lock, flags); |
887 | } | 881 | } |
diff --git a/arch/powerpc/platforms/pseries/xics.h b/arch/powerpc/platforms/pseries/xics.h index 9ffd809d29e2..c26bcff47b6d 100644 --- a/arch/powerpc/platforms/pseries/xics.h +++ b/arch/powerpc/platforms/pseries/xics.h | |||
@@ -16,7 +16,8 @@ | |||
16 | 16 | ||
17 | extern void xics_init_IRQ(void); | 17 | extern void xics_init_IRQ(void); |
18 | extern void xics_setup_cpu(void); | 18 | extern void xics_setup_cpu(void); |
19 | extern void xics_teardown_cpu(int secondary); | 19 | extern void xics_teardown_cpu(void); |
20 | extern void xics_kexec_teardown_cpu(int secondary); | ||
20 | extern void xics_cause_IPI(int cpu); | 21 | extern void xics_cause_IPI(int cpu); |
21 | extern void xics_request_IPIs(void); | 22 | extern void xics_request_IPIs(void); |
22 | extern void xics_migrate_irqs_away(void); | 23 | extern void xics_migrate_irqs_away(void); |