aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel')
-rw-r--r--arch/ppc64/kernel/head.S16
-rw-r--r--arch/ppc64/kernel/iSeries_vio.c21
-rw-r--r--arch/ppc64/kernel/lparcfg.c1
-rw-r--r--arch/ppc64/kernel/of_device.c2
-rw-r--r--arch/ppc64/kernel/pSeries_vio.c19
-rw-r--r--arch/ppc64/kernel/prom_init.c5
-rw-r--r--arch/ppc64/kernel/vio.c73
7 files changed, 76 insertions, 61 deletions
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index cccec4902646..036959775623 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -1269,7 +1269,21 @@ initial_stab:
1269 .= 0x7000 1269 .= 0x7000
1270 .globl fwnmi_data_area 1270 .globl fwnmi_data_area
1271fwnmi_data_area: 1271fwnmi_data_area:
1272 .space PAGE_SIZE 1272
1273 /* iSeries does not use the FWNMI stuff, so it is safe to put
1274 * this here, even if we later allow kernels that will boot on
1275 * both pSeries and iSeries */
1276#ifdef CONFIG_PPC_ISERIES
1277 . = LPARMAP_PHYS
1278#include "lparmap.s"
1279/*
1280 * This ".text" is here for old compilers that generate a trailing
1281 * .note section when compiling .c files to .s
1282 */
1283 .text
1284#endif /* CONFIG_PPC_ISERIES */
1285
1286 . = 0x8000
1273 1287
1274/* 1288/*
1275 * On pSeries, secondary processors spin in the following code. 1289 * On pSeries, secondary processors spin in the following code.
diff --git a/arch/ppc64/kernel/iSeries_vio.c b/arch/ppc64/kernel/iSeries_vio.c
index b4268cc4ba48..6b754b0c8344 100644
--- a/arch/ppc64/kernel/iSeries_vio.c
+++ b/arch/ppc64/kernel/iSeries_vio.c
@@ -68,7 +68,7 @@ static void __init iommu_vio_init(void)
68} 68}
69 69
70/** 70/**
71 * vio_register_device: - Register a new vio device. 71 * vio_register_device_iseries: - Register a new iSeries vio device.
72 * @voidev: The device to register. 72 * @voidev: The device to register.
73 */ 73 */
74static struct vio_dev *__init vio_register_device_iseries(char *type, 74static struct vio_dev *__init vio_register_device_iseries(char *type,
@@ -76,7 +76,7 @@ static struct vio_dev *__init vio_register_device_iseries(char *type,
76{ 76{
77 struct vio_dev *viodev; 77 struct vio_dev *viodev;
78 78
79 /* allocate a vio_dev for this node */ 79 /* allocate a vio_dev for this device */
80 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); 80 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
81 if (!viodev) 81 if (!viodev)
82 return NULL; 82 return NULL;
@@ -84,8 +84,15 @@ static struct vio_dev *__init vio_register_device_iseries(char *type,
84 84
85 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num); 85 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
86 86
87 return vio_register_device_common(viodev, viodev->dev.bus_id, type, 87 viodev->name = viodev->dev.bus_id;
88 unit_num, &vio_iommu_table); 88 viodev->type = type;
89 viodev->unit_address = unit_num;
90 viodev->iommu_table = &vio_iommu_table;
91 if (vio_register_device(viodev) == NULL) {
92 kfree(viodev);
93 return NULL;
94 }
95 return viodev;
89} 96}
90 97
91void __init probe_bus_iseries(void) 98void __init probe_bus_iseries(void)
@@ -124,6 +131,10 @@ static int vio_match_device_iseries(const struct vio_device_id *id,
124 return strncmp(dev->type, id->type, strlen(id->type)) == 0; 131 return strncmp(dev->type, id->type, strlen(id->type)) == 0;
125} 132}
126 133
134static struct vio_bus_ops vio_bus_ops_iseries = {
135 .match = vio_match_device_iseries,
136};
137
127/** 138/**
128 * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus 139 * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
129 */ 140 */
@@ -131,7 +142,7 @@ static int __init vio_bus_init_iseries(void)
131{ 142{
132 int err; 143 int err;
133 144
134 err = vio_bus_init(vio_match_device_iseries, NULL, NULL); 145 err = vio_bus_init(&vio_bus_ops_iseries);
135 if (err == 0) { 146 if (err == 0) {
136 iommu_vio_init(); 147 iommu_vio_init();
137 vio_bus_device.iommu_table = &vio_iommu_table; 148 vio_bus_device.iommu_table = &vio_iommu_table;
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index 9d034ff062b1..edad361a8db0 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -273,6 +273,7 @@ static void parse_system_parameter_string(struct seq_file *m)
273 if (!workbuffer) { 273 if (!workbuffer) {
274 printk(KERN_ERR "%s %s kmalloc failure at line %d \n", 274 printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
275 __FILE__, __FUNCTION__, __LINE__); 275 __FILE__, __FUNCTION__, __LINE__);
276 kfree(local_buffer);
276 return; 277 return;
277 } 278 }
278#ifdef LPARCFG_DEBUG 279#ifdef LPARCFG_DEBUG
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index b80e81984ba8..da580812ddfe 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -236,7 +236,6 @@ void of_device_unregister(struct of_device *ofdev)
236struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) 236struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
237{ 237{
238 struct of_device *dev; 238 struct of_device *dev;
239 u32 *reg;
240 239
241 dev = kmalloc(sizeof(*dev), GFP_KERNEL); 240 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
242 if (!dev) 241 if (!dev)
@@ -250,7 +249,6 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
250 dev->dev.bus = &of_platform_bus_type; 249 dev->dev.bus = &of_platform_bus_type;
251 dev->dev.release = of_release_dev; 250 dev->dev.release = of_release_dev;
252 251
253 reg = (u32 *)get_property(np, "reg", NULL);
254 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); 252 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
255 253
256 if (of_device_register(dev) != 0) { 254 if (of_device_register(dev) != 0) {
diff --git a/arch/ppc64/kernel/pSeries_vio.c b/arch/ppc64/kernel/pSeries_vio.c
index 338f9e1bdc09..e0ae06f58f86 100644
--- a/arch/ppc64/kernel/pSeries_vio.c
+++ b/arch/ppc64/kernel/pSeries_vio.c
@@ -19,6 +19,7 @@
19#include <linux/kobject.h> 19#include <linux/kobject.h>
20#include <asm/iommu.h> 20#include <asm/iommu.h>
21#include <asm/dma.h> 21#include <asm/dma.h>
22#include <asm/prom.h>
22#include <asm/vio.h> 23#include <asm/vio.h>
23#include <asm/hvcall.h> 24#include <asm/hvcall.h>
24 25
@@ -75,6 +76,12 @@ static void vio_unregister_device_pseries(struct vio_dev *viodev)
75 device_remove_file(&viodev->dev, &dev_attr_devspec); 76 device_remove_file(&viodev->dev, &dev_attr_devspec);
76} 77}
77 78
79static struct vio_bus_ops vio_bus_ops_pseries = {
80 .match = vio_match_device_pseries,
81 .unregister_device = vio_unregister_device_pseries,
82 .release_device = vio_release_device_pseries,
83};
84
78/** 85/**
79 * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus 86 * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
80 */ 87 */
@@ -82,9 +89,7 @@ static int __init vio_bus_init_pseries(void)
82{ 89{
83 int err; 90 int err;
84 91
85 err = vio_bus_init(vio_match_device_pseries, 92 err = vio_bus_init(&vio_bus_ops_pseries);
86 vio_unregister_device_pseries,
87 vio_release_device_pseries);
88 if (err == 0) 93 if (err == 0)
89 probe_bus_pseries(); 94 probe_bus_pseries();
90 return err; 95 return err;
@@ -181,11 +186,13 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
181 } 186 }
182 187
183 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); 188 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
189 viodev->name = of_node->name;
190 viodev->type = of_node->type;
191 viodev->unit_address = *unit_address;
192 viodev->iommu_table = vio_build_iommu_table(viodev);
184 193
185 /* register with generic device framework */ 194 /* register with generic device framework */
186 if (vio_register_device_common(viodev, of_node->name, of_node->type, 195 if (vio_register_device(viodev) == NULL) {
187 *unit_address, vio_build_iommu_table(viodev))
188 == NULL) {
189 /* XXX free TCE table */ 196 /* XXX free TCE table */
190 kfree(viodev); 197 kfree(viodev);
191 return NULL; 198 return NULL;
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index adcf972711fc..122283a1d39a 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -892,7 +892,10 @@ static void __init prom_init_mem(void)
892 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) 892 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
893 RELOC(alloc_top) = RELOC(rmo_top); 893 RELOC(alloc_top) = RELOC(rmo_top);
894 else 894 else
895 RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top)); 895 /* Some RS64 machines have buggy firmware where claims up at 1GB
896 * fails. Cap at 768MB as a workaround. Still plenty of room.
897 */
898 RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top));
896 899
897 prom_printf("memory layout at init:\n"); 900 prom_printf("memory layout at init:\n");
898 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); 901 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index 3b790bafcaad..c90e1dd875ce 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -32,14 +32,13 @@ struct vio_dev vio_bus_device = { /* fake "parent" device */
32 .dev.bus = &vio_bus_type, 32 .dev.bus = &vio_bus_type,
33}; 33};
34 34
35static int (*is_match)(const struct vio_device_id *id, 35static struct vio_bus_ops vio_bus_ops;
36 const struct vio_dev *dev);
37static void (*unregister_device_callback)(struct vio_dev *dev);
38static void (*release_device_callback)(struct device *dev);
39 36
40/* convert from struct device to struct vio_dev and pass to driver. 37/*
38 * Convert from struct device to struct vio_dev and pass to driver.
41 * dev->driver has already been set by generic code because vio_bus_match 39 * dev->driver has already been set by generic code because vio_bus_match
42 * succeeded. */ 40 * succeeded.
41 */
43static int vio_bus_probe(struct device *dev) 42static int vio_bus_probe(struct device *dev)
44{ 43{
45 struct vio_dev *viodev = to_vio_dev(dev); 44 struct vio_dev *viodev = to_vio_dev(dev);
@@ -51,9 +50,8 @@ static int vio_bus_probe(struct device *dev)
51 return error; 50 return error;
52 51
53 id = vio_match_device(viodrv->id_table, viodev); 52 id = vio_match_device(viodrv->id_table, viodev);
54 if (id) { 53 if (id)
55 error = viodrv->probe(viodev, id); 54 error = viodrv->probe(viodev, id);
56 }
57 55
58 return error; 56 return error;
59} 57}
@@ -64,9 +62,8 @@ static int vio_bus_remove(struct device *dev)
64 struct vio_dev *viodev = to_vio_dev(dev); 62 struct vio_dev *viodev = to_vio_dev(dev);
65 struct vio_driver *viodrv = to_vio_driver(dev->driver); 63 struct vio_driver *viodrv = to_vio_driver(dev->driver);
66 64
67 if (viodrv->remove) { 65 if (viodrv->remove)
68 return viodrv->remove(viodev); 66 return viodrv->remove(viodev);
69 }
70 67
71 /* driver can't remove */ 68 /* driver can't remove */
72 return 1; 69 return 1;
@@ -102,19 +99,20 @@ void vio_unregister_driver(struct vio_driver *viodrv)
102EXPORT_SYMBOL(vio_unregister_driver); 99EXPORT_SYMBOL(vio_unregister_driver);
103 100
104/** 101/**
105 * vio_match_device: - Tell if a VIO device has a matching VIO device id structure. 102 * vio_match_device: - Tell if a VIO device has a matching
106 * @ids: array of VIO device id structures to search in 103 * VIO device id structure.
107 * @dev: the VIO device structure to match against 104 * @ids: array of VIO device id structures to search in
105 * @dev: the VIO device structure to match against
108 * 106 *
109 * Used by a driver to check whether a VIO device present in the 107 * Used by a driver to check whether a VIO device present in the
110 * system is in its list of supported devices. Returns the matching 108 * system is in its list of supported devices. Returns the matching
111 * vio_device_id structure or NULL if there is no match. 109 * vio_device_id structure or NULL if there is no match.
112 */ 110 */
113static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, 111static const struct vio_device_id *vio_match_device(
114 const struct vio_dev *dev) 112 const struct vio_device_id *ids, const struct vio_dev *dev)
115{ 113{
116 while (ids->type) { 114 while (ids->type[0] != '\0') {
117 if (is_match(ids, dev)) 115 if (vio_bus_ops.match(ids, dev))
118 return ids; 116 return ids;
119 ids++; 117 ids++;
120 } 118 }
@@ -124,16 +122,11 @@ static const struct vio_device_id * vio_match_device(const struct vio_device_id
124/** 122/**
125 * vio_bus_init: - Initialize the virtual IO bus 123 * vio_bus_init: - Initialize the virtual IO bus
126 */ 124 */
127int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id, 125int __init vio_bus_init(struct vio_bus_ops *ops)
128 const struct vio_dev *dev),
129 void (*unregister_dev)(struct vio_dev *),
130 void (*release_dev)(struct device *))
131{ 126{
132 int err; 127 int err;
133 128
134 is_match = match_func; 129 vio_bus_ops = *ops;
135 unregister_device_callback = unregister_dev;
136 release_device_callback = release_dev;
137 130
138 err = bus_register(&vio_bus_type); 131 err = bus_register(&vio_bus_type);
139 if (err) { 132 if (err) {
@@ -141,7 +134,8 @@ int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id,
141 return err; 134 return err;
142 } 135 }
143 136
144 /* the fake parent of all vio devices, just to give us 137 /*
138 * The fake parent of all vio devices, just to give us
145 * a nice directory 139 * a nice directory
146 */ 140 */
147 err = device_register(&vio_bus_device.dev); 141 err = device_register(&vio_bus_device.dev);
@@ -157,25 +151,20 @@ int __init vio_bus_init(int (*match_func)(const struct vio_device_id *id,
157/* vio_dev refcount hit 0 */ 151/* vio_dev refcount hit 0 */
158static void __devinit vio_dev_release(struct device *dev) 152static void __devinit vio_dev_release(struct device *dev)
159{ 153{
160 if (release_device_callback) 154 if (vio_bus_ops.release_device)
161 release_device_callback(dev); 155 vio_bus_ops.release_device(dev);
162 kfree(to_vio_dev(dev)); 156 kfree(to_vio_dev(dev));
163} 157}
164 158
165static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf) 159static ssize_t viodev_show_name(struct device *dev,
160 struct device_attribute *attr, char *buf)
166{ 161{
167 return sprintf(buf, "%s\n", to_vio_dev(dev)->name); 162 return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
168} 163}
169DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); 164DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
170 165
171struct vio_dev * __devinit vio_register_device_common( 166struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
172 struct vio_dev *viodev, char *name, char *type,
173 uint32_t unit_address, struct iommu_table *iommu_table)
174{ 167{
175 viodev->name = name;
176 viodev->type = type;
177 viodev->unit_address = unit_address;
178 viodev->iommu_table = iommu_table;
179 /* init generic 'struct device' fields: */ 168 /* init generic 'struct device' fields: */
180 viodev->dev.parent = &vio_bus_device.dev; 169 viodev->dev.parent = &vio_bus_device.dev;
181 viodev->dev.bus = &vio_bus_type; 170 viodev->dev.bus = &vio_bus_type;
@@ -194,8 +183,8 @@ struct vio_dev * __devinit vio_register_device_common(
194 183
195void __devinit vio_unregister_device(struct vio_dev *viodev) 184void __devinit vio_unregister_device(struct vio_dev *viodev)
196{ 185{
197 if (unregister_device_callback) 186 if (vio_bus_ops.unregister_device)
198 unregister_device_callback(viodev); 187 vio_bus_ops.unregister_device(viodev);
199 device_remove_file(&viodev->dev, &dev_attr_name); 188 device_remove_file(&viodev->dev, &dev_attr_name);
200 device_unregister(&viodev->dev); 189 device_unregister(&viodev->dev);
201} 190}
@@ -262,16 +251,8 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv)
262 const struct vio_dev *vio_dev = to_vio_dev(dev); 251 const struct vio_dev *vio_dev = to_vio_dev(dev);
263 struct vio_driver *vio_drv = to_vio_driver(drv); 252 struct vio_driver *vio_drv = to_vio_driver(drv);
264 const struct vio_device_id *ids = vio_drv->id_table; 253 const struct vio_device_id *ids = vio_drv->id_table;
265 const struct vio_device_id *found_id;
266
267 if (!ids)
268 return 0;
269 254
270 found_id = vio_match_device(ids, vio_dev); 255 return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
271 if (found_id)
272 return 1;
273
274 return 0;
275} 256}
276 257
277struct bus_type vio_bus_type = { 258struct bus_type vio_bus_type = {