diff options
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/kernel/devices.c | 25 | ||||
-rw-r--r-- | arch/sparc/kernel/irq.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/of_device.c | 207 | ||||
-rw-r--r-- | arch/sparc/kernel/prom.c | 9 | ||||
-rw-r--r-- | arch/sparc/kernel/setup.c | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/smp.c | 97 | ||||
-rw-r--r-- | arch/sparc/kernel/sparc_ksyms.c | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4d_smp.c | 105 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4m_smp.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc.c | 49 | ||||
-rw-r--r-- | arch/sparc/kernel/time.c | 74 | ||||
-rw-r--r-- | arch/sparc/mm/io-unit.c | 1 | ||||
-rw-r--r-- | arch/sparc/prom/tree.c | 18 |
13 files changed, 353 insertions, 243 deletions
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index adba9dfee35e..af90a5f9ab57 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <asm/page.h> | 16 | #include <asm/page.h> |
17 | #include <asm/oplib.h> | 17 | #include <asm/oplib.h> |
18 | #include <asm/prom.h> | ||
18 | #include <asm/smp.h> | 19 | #include <asm/smp.h> |
19 | #include <asm/system.h> | 20 | #include <asm/system.h> |
20 | #include <asm/cpudata.h> | 21 | #include <asm/cpudata.h> |
@@ -34,12 +35,6 @@ static int check_cpu_node(int nd, int *cur_inst, | |||
34 | int (*compare)(int, int, void *), void *compare_arg, | 35 | int (*compare)(int, int, void *), void *compare_arg, |
35 | int *prom_node, int *mid) | 36 | int *prom_node, int *mid) |
36 | { | 37 | { |
37 | char node_str[128]; | ||
38 | |||
39 | prom_getstring(nd, "device_type", node_str, sizeof(node_str)); | ||
40 | if (strcmp(node_str, "cpu")) | ||
41 | return -ENODEV; | ||
42 | |||
43 | if (!compare(nd, *cur_inst, compare_arg)) { | 38 | if (!compare(nd, *cur_inst, compare_arg)) { |
44 | if (prom_node) | 39 | if (prom_node) |
45 | *prom_node = nd; | 40 | *prom_node = nd; |
@@ -59,20 +54,14 @@ static int check_cpu_node(int nd, int *cur_inst, | |||
59 | static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, | 54 | static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, |
60 | int *prom_node, int *mid) | 55 | int *prom_node, int *mid) |
61 | { | 56 | { |
62 | int nd, cur_inst, err; | 57 | struct device_node *dp; |
58 | int cur_inst; | ||
63 | 59 | ||
64 | nd = prom_root_node; | ||
65 | cur_inst = 0; | 60 | cur_inst = 0; |
66 | 61 | for_each_node_by_type(dp, "cpu") { | |
67 | err = check_cpu_node(nd, &cur_inst, compare, compare_arg, | 62 | int err = check_cpu_node(dp->node, &cur_inst, |
68 | prom_node, mid); | 63 | compare, compare_arg, |
69 | if (!err) | 64 | prom_node, mid); |
70 | return 0; | ||
71 | |||
72 | nd = prom_getchild(nd); | ||
73 | while ((nd = prom_getsibling(nd)) != 0) { | ||
74 | err = check_cpu_node(nd, &cur_inst, compare, compare_arg, | ||
75 | prom_node, mid); | ||
76 | if (!err) | 65 | if (!err) |
77 | return 0; | 66 | return 0; |
78 | } | 67 | } |
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index cde73327ca96..72f0201051a0 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c | |||
@@ -329,7 +329,7 @@ void handler_irq(int irq, struct pt_regs * regs) | |||
329 | disable_pil_irq(irq); | 329 | disable_pil_irq(irq); |
330 | #ifdef CONFIG_SMP | 330 | #ifdef CONFIG_SMP |
331 | /* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */ | 331 | /* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */ |
332 | if(irq < 10) | 332 | if((sparc_cpu_model==sun4m) && (irq < 10)) |
333 | smp4m_irq_rotate(cpu); | 333 | smp4m_irq_rotate(cpu); |
334 | #endif | 334 | #endif |
335 | action = sparc_irq[irq].action; | 335 | action = sparc_irq[irq].action; |
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index bc956c530376..97bf87e8cdde 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c | |||
@@ -183,7 +183,7 @@ struct bus_type of_bus_type = { | |||
183 | }; | 183 | }; |
184 | EXPORT_SYMBOL(of_bus_type); | 184 | EXPORT_SYMBOL(of_bus_type); |
185 | 185 | ||
186 | static inline u64 of_read_addr(u32 *cell, int size) | 186 | static inline u64 of_read_addr(const u32 *cell, int size) |
187 | { | 187 | { |
188 | u64 r = 0; | 188 | u64 r = 0; |
189 | while (size--) | 189 | while (size--) |
@@ -209,8 +209,8 @@ struct of_bus { | |||
209 | int (*match)(struct device_node *parent); | 209 | int (*match)(struct device_node *parent); |
210 | void (*count_cells)(struct device_node *child, | 210 | void (*count_cells)(struct device_node *child, |
211 | int *addrc, int *sizec); | 211 | int *addrc, int *sizec); |
212 | u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna); | 212 | int (*map)(u32 *addr, const u32 *range, |
213 | int (*translate)(u32 *addr, u64 offset, int na); | 213 | int na, int ns, int pna); |
214 | unsigned int (*get_flags)(u32 *addr); | 214 | unsigned int (*get_flags)(u32 *addr); |
215 | }; | 215 | }; |
216 | 216 | ||
@@ -224,27 +224,49 @@ static void of_bus_default_count_cells(struct device_node *dev, | |||
224 | get_cells(dev, addrc, sizec); | 224 | get_cells(dev, addrc, sizec); |
225 | } | 225 | } |
226 | 226 | ||
227 | static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) | 227 | /* Make sure the least significant 64-bits are in-range. Even |
228 | * for 3 or 4 cell values it is a good enough approximation. | ||
229 | */ | ||
230 | static int of_out_of_range(const u32 *addr, const u32 *base, | ||
231 | const u32 *size, int na, int ns) | ||
228 | { | 232 | { |
229 | u64 cp, s, da; | 233 | u64 a = of_read_addr(addr, na); |
234 | u64 b = of_read_addr(base, na); | ||
230 | 235 | ||
231 | cp = of_read_addr(range, na); | 236 | if (a < b) |
232 | s = of_read_addr(range + na + pna, ns); | 237 | return 1; |
233 | da = of_read_addr(addr, na); | ||
234 | 238 | ||
235 | if (da < cp || da >= (cp + s)) | 239 | b += of_read_addr(size, ns); |
236 | return OF_BAD_ADDR; | 240 | if (a >= b) |
237 | return da - cp; | 241 | return 1; |
242 | |||
243 | return 0; | ||
238 | } | 244 | } |
239 | 245 | ||
240 | static int of_bus_default_translate(u32 *addr, u64 offset, int na) | 246 | static int of_bus_default_map(u32 *addr, const u32 *range, |
247 | int na, int ns, int pna) | ||
241 | { | 248 | { |
242 | u64 a = of_read_addr(addr, na); | 249 | u32 result[OF_MAX_ADDR_CELLS]; |
243 | memset(addr, 0, na * 4); | 250 | int i; |
244 | a += offset; | 251 | |
245 | if (na > 1) | 252 | if (ns > 2) { |
246 | addr[na - 2] = a >> 32; | 253 | printk("of_device: Cannot handle size cells (%d) > 2.", ns); |
247 | addr[na - 1] = a & 0xffffffffu; | 254 | return -EINVAL; |
255 | } | ||
256 | |||
257 | if (of_out_of_range(addr, range, range + na + pna, na, ns)) | ||
258 | return -EINVAL; | ||
259 | |||
260 | /* Start with the parent range base. */ | ||
261 | memcpy(result, range + na, pna * 4); | ||
262 | |||
263 | /* Add in the child address offset. */ | ||
264 | for (i = 0; i < na; i++) | ||
265 | result[pna - 1 - i] += | ||
266 | (addr[na - 1 - i] - | ||
267 | range[na - 1 - i]); | ||
268 | |||
269 | memcpy(addr, result, pna * 4); | ||
248 | 270 | ||
249 | return 0; | 271 | return 0; |
250 | } | 272 | } |
@@ -254,14 +276,26 @@ static unsigned int of_bus_default_get_flags(u32 *addr) | |||
254 | return IORESOURCE_MEM; | 276 | return IORESOURCE_MEM; |
255 | } | 277 | } |
256 | 278 | ||
257 | |||
258 | /* | 279 | /* |
259 | * PCI bus specific translator | 280 | * PCI bus specific translator |
260 | */ | 281 | */ |
261 | 282 | ||
262 | static int of_bus_pci_match(struct device_node *np) | 283 | static int of_bus_pci_match(struct device_node *np) |
263 | { | 284 | { |
264 | return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex"); | 285 | if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { |
286 | /* Do not do PCI specific frobbing if the | ||
287 | * PCI bridge lacks a ranges property. We | ||
288 | * want to pass it through up to the next | ||
289 | * parent as-is, not with the PCI translate | ||
290 | * method which chops off the top address cell. | ||
291 | */ | ||
292 | if (!of_find_property(np, "ranges", NULL)) | ||
293 | return 0; | ||
294 | |||
295 | return 1; | ||
296 | } | ||
297 | |||
298 | return 0; | ||
265 | } | 299 | } |
266 | 300 | ||
267 | static void of_bus_pci_count_cells(struct device_node *np, | 301 | static void of_bus_pci_count_cells(struct device_node *np, |
@@ -273,27 +307,32 @@ static void of_bus_pci_count_cells(struct device_node *np, | |||
273 | *sizec = 2; | 307 | *sizec = 2; |
274 | } | 308 | } |
275 | 309 | ||
276 | static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) | 310 | static int of_bus_pci_map(u32 *addr, const u32 *range, |
311 | int na, int ns, int pna) | ||
277 | { | 312 | { |
278 | u64 cp, s, da; | 313 | u32 result[OF_MAX_ADDR_CELLS]; |
314 | int i; | ||
279 | 315 | ||
280 | /* Check address type match */ | 316 | /* Check address type match */ |
281 | if ((addr[0] ^ range[0]) & 0x03000000) | 317 | if ((addr[0] ^ range[0]) & 0x03000000) |
282 | return OF_BAD_ADDR; | 318 | return -EINVAL; |
283 | 319 | ||
284 | /* Read address values, skipping high cell */ | 320 | if (of_out_of_range(addr + 1, range + 1, range + na + pna, |
285 | cp = of_read_addr(range + 1, na - 1); | 321 | na - 1, ns)) |
286 | s = of_read_addr(range + na + pna, ns); | 322 | return -EINVAL; |
287 | da = of_read_addr(addr + 1, na - 1); | ||
288 | 323 | ||
289 | if (da < cp || da >= (cp + s)) | 324 | /* Start with the parent range base. */ |
290 | return OF_BAD_ADDR; | 325 | memcpy(result, range + na, pna * 4); |
291 | return da - cp; | ||
292 | } | ||
293 | 326 | ||
294 | static int of_bus_pci_translate(u32 *addr, u64 offset, int na) | 327 | /* Add in the child address offset, skipping high cell. */ |
295 | { | 328 | for (i = 0; i < na - 1; i++) |
296 | return of_bus_default_translate(addr + 1, offset, na - 1); | 329 | result[pna - 1 - i] += |
330 | (addr[na - 1 - i] - | ||
331 | range[na - 1 - i]); | ||
332 | |||
333 | memcpy(addr, result, pna * 4); | ||
334 | |||
335 | return 0; | ||
297 | } | 336 | } |
298 | 337 | ||
299 | static unsigned int of_bus_pci_get_flags(u32 *addr) | 338 | static unsigned int of_bus_pci_get_flags(u32 *addr) |
@@ -332,16 +371,11 @@ static void of_bus_sbus_count_cells(struct device_node *child, | |||
332 | *sizec = 1; | 371 | *sizec = 1; |
333 | } | 372 | } |
334 | 373 | ||
335 | static u64 of_bus_sbus_map(u32 *addr, u32 *range, int na, int ns, int pna) | 374 | static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) |
336 | { | 375 | { |
337 | return of_bus_default_map(addr, range, na, ns, pna); | 376 | return of_bus_default_map(addr, range, na, ns, pna); |
338 | } | 377 | } |
339 | 378 | ||
340 | static int of_bus_sbus_translate(u32 *addr, u64 offset, int na) | ||
341 | { | ||
342 | return of_bus_default_translate(addr, offset, na); | ||
343 | } | ||
344 | |||
345 | static unsigned int of_bus_sbus_get_flags(u32 *addr) | 379 | static unsigned int of_bus_sbus_get_flags(u32 *addr) |
346 | { | 380 | { |
347 | return IORESOURCE_MEM; | 381 | return IORESOURCE_MEM; |
@@ -360,7 +394,6 @@ static struct of_bus of_busses[] = { | |||
360 | .match = of_bus_pci_match, | 394 | .match = of_bus_pci_match, |
361 | .count_cells = of_bus_pci_count_cells, | 395 | .count_cells = of_bus_pci_count_cells, |
362 | .map = of_bus_pci_map, | 396 | .map = of_bus_pci_map, |
363 | .translate = of_bus_pci_translate, | ||
364 | .get_flags = of_bus_pci_get_flags, | 397 | .get_flags = of_bus_pci_get_flags, |
365 | }, | 398 | }, |
366 | /* SBUS */ | 399 | /* SBUS */ |
@@ -370,7 +403,6 @@ static struct of_bus of_busses[] = { | |||
370 | .match = of_bus_sbus_match, | 403 | .match = of_bus_sbus_match, |
371 | .count_cells = of_bus_sbus_count_cells, | 404 | .count_cells = of_bus_sbus_count_cells, |
372 | .map = of_bus_sbus_map, | 405 | .map = of_bus_sbus_map, |
373 | .translate = of_bus_sbus_translate, | ||
374 | .get_flags = of_bus_sbus_get_flags, | 406 | .get_flags = of_bus_sbus_get_flags, |
375 | }, | 407 | }, |
376 | /* Default */ | 408 | /* Default */ |
@@ -380,7 +412,6 @@ static struct of_bus of_busses[] = { | |||
380 | .match = NULL, | 412 | .match = NULL, |
381 | .count_cells = of_bus_default_count_cells, | 413 | .count_cells = of_bus_default_count_cells, |
382 | .map = of_bus_default_map, | 414 | .map = of_bus_default_map, |
383 | .translate = of_bus_default_translate, | ||
384 | .get_flags = of_bus_default_get_flags, | 415 | .get_flags = of_bus_default_get_flags, |
385 | }, | 416 | }, |
386 | }; | 417 | }; |
@@ -405,33 +436,34 @@ static int __init build_one_resource(struct device_node *parent, | |||
405 | u32 *ranges; | 436 | u32 *ranges; |
406 | unsigned int rlen; | 437 | unsigned int rlen; |
407 | int rone; | 438 | int rone; |
408 | u64 offset = OF_BAD_ADDR; | ||
409 | 439 | ||
410 | ranges = of_get_property(parent, "ranges", &rlen); | 440 | ranges = of_get_property(parent, "ranges", &rlen); |
411 | if (ranges == NULL || rlen == 0) { | 441 | if (ranges == NULL || rlen == 0) { |
412 | offset = of_read_addr(addr, na); | 442 | u32 result[OF_MAX_ADDR_CELLS]; |
413 | memset(addr, 0, pna * 4); | 443 | int i; |
414 | goto finish; | 444 | |
445 | memset(result, 0, pna * 4); | ||
446 | for (i = 0; i < na; i++) | ||
447 | result[pna - 1 - i] = | ||
448 | addr[na - 1 - i]; | ||
449 | |||
450 | memcpy(addr, result, pna * 4); | ||
451 | return 0; | ||
415 | } | 452 | } |
416 | 453 | ||
417 | /* Now walk through the ranges */ | 454 | /* Now walk through the ranges */ |
418 | rlen /= 4; | 455 | rlen /= 4; |
419 | rone = na + pna + ns; | 456 | rone = na + pna + ns; |
420 | for (; rlen >= rone; rlen -= rone, ranges += rone) { | 457 | for (; rlen >= rone; rlen -= rone, ranges += rone) { |
421 | offset = bus->map(addr, ranges, na, ns, pna); | 458 | if (!bus->map(addr, ranges, na, ns, pna)) |
422 | if (offset != OF_BAD_ADDR) | 459 | return 0; |
423 | break; | ||
424 | } | 460 | } |
425 | if (offset == OF_BAD_ADDR) | ||
426 | return 1; | ||
427 | 461 | ||
428 | memcpy(addr, ranges + na, 4 * pna); | 462 | return 1; |
429 | |||
430 | finish: | ||
431 | /* Translate it into parent bus space */ | ||
432 | return pbus->translate(addr, offset, pna); | ||
433 | } | 463 | } |
434 | 464 | ||
465 | static int of_resource_verbose; | ||
466 | |||
435 | static void __init build_device_resources(struct of_device *op, | 467 | static void __init build_device_resources(struct of_device *op, |
436 | struct device *parent) | 468 | struct device *parent) |
437 | { | 469 | { |
@@ -497,7 +529,8 @@ static void __init build_device_resources(struct of_device *op, | |||
497 | pbus = of_match_bus(pp); | 529 | pbus = of_match_bus(pp); |
498 | pbus->count_cells(dp, &pna, &pns); | 530 | pbus->count_cells(dp, &pna, &pns); |
499 | 531 | ||
500 | if (build_one_resource(dp, bus, pbus, addr, dna, dns, pna)) | 532 | if (build_one_resource(dp, bus, pbus, addr, |
533 | dna, dns, pna)) | ||
501 | break; | 534 | break; |
502 | 535 | ||
503 | dna = pna; | 536 | dna = pna; |
@@ -507,6 +540,12 @@ static void __init build_device_resources(struct of_device *op, | |||
507 | 540 | ||
508 | build_res: | 541 | build_res: |
509 | memset(r, 0, sizeof(*r)); | 542 | memset(r, 0, sizeof(*r)); |
543 | |||
544 | if (of_resource_verbose) | ||
545 | printk("%s reg[%d] -> %llx\n", | ||
546 | op->node->full_name, index, | ||
547 | result); | ||
548 | |||
510 | if (result != OF_BAD_ADDR) { | 549 | if (result != OF_BAD_ADDR) { |
511 | r->start = result & 0xffffffff; | 550 | r->start = result & 0xffffffff; |
512 | r->end = result + size - 1; | 551 | r->end = result + size - 1; |
@@ -557,14 +596,41 @@ static struct of_device * __init scan_one_device(struct device_node *dp, | |||
557 | static int pil_to_sbus[] = { | 596 | static int pil_to_sbus[] = { |
558 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, | 597 | 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, |
559 | }; | 598 | }; |
560 | struct device_node *busp = dp->parent; | 599 | struct device_node *io_unit, *sbi = dp->parent; |
561 | struct linux_prom_registers *regs; | 600 | struct linux_prom_registers *regs; |
562 | int board = of_getintprop_default(busp, "board#", 0); | 601 | int board, slot; |
563 | int slot; | 602 | |
603 | while (sbi) { | ||
604 | if (!strcmp(sbi->name, "sbi")) | ||
605 | break; | ||
606 | |||
607 | sbi = sbi->parent; | ||
608 | } | ||
609 | if (!sbi) | ||
610 | goto build_resources; | ||
564 | 611 | ||
565 | regs = of_get_property(dp, "reg", NULL); | 612 | regs = of_get_property(dp, "reg", NULL); |
613 | if (!regs) | ||
614 | goto build_resources; | ||
615 | |||
566 | slot = regs->which_io; | 616 | slot = regs->which_io; |
567 | 617 | ||
618 | /* If SBI's parent is not io-unit or the io-unit lacks | ||
619 | * a "board#" property, something is very wrong. | ||
620 | */ | ||
621 | if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { | ||
622 | printk("%s: Error, parent is not io-unit.\n", | ||
623 | sbi->full_name); | ||
624 | goto build_resources; | ||
625 | } | ||
626 | io_unit = sbi->parent; | ||
627 | board = of_getintprop_default(io_unit, "board#", -1); | ||
628 | if (board == -1) { | ||
629 | printk("%s: Error, lacks board# property.\n", | ||
630 | io_unit->full_name); | ||
631 | goto build_resources; | ||
632 | } | ||
633 | |||
568 | for (i = 0; i < op->num_irqs; i++) { | 634 | for (i = 0; i < op->num_irqs; i++) { |
569 | int this_irq = op->irqs[i]; | 635 | int this_irq = op->irqs[i]; |
570 | int sbusl = pil_to_sbus[this_irq]; | 636 | int sbusl = pil_to_sbus[this_irq]; |
@@ -578,6 +644,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, | |||
578 | } | 644 | } |
579 | } | 645 | } |
580 | 646 | ||
647 | build_resources: | ||
581 | build_device_resources(op, parent); | 648 | build_device_resources(op, parent); |
582 | 649 | ||
583 | op->dev.parent = parent; | 650 | op->dev.parent = parent; |
@@ -643,6 +710,18 @@ static int __init of_bus_driver_init(void) | |||
643 | 710 | ||
644 | postcore_initcall(of_bus_driver_init); | 711 | postcore_initcall(of_bus_driver_init); |
645 | 712 | ||
713 | static int __init of_debug(char *str) | ||
714 | { | ||
715 | int val = 0; | ||
716 | |||
717 | get_option(&str, &val); | ||
718 | if (val & 1) | ||
719 | of_resource_verbose = 1; | ||
720 | return 1; | ||
721 | } | ||
722 | |||
723 | __setup("of_debug=", of_debug); | ||
724 | |||
646 | int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) | 725 | int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) |
647 | { | 726 | { |
648 | /* initialize common driver fields */ | 727 | /* initialize common driver fields */ |
@@ -695,9 +774,11 @@ int of_device_register(struct of_device *ofdev) | |||
695 | if (rc) | 774 | if (rc) |
696 | return rc; | 775 | return rc; |
697 | 776 | ||
698 | device_create_file(&ofdev->dev, &dev_attr_devspec); | 777 | rc = device_create_file(&ofdev->dev, &dev_attr_devspec); |
778 | if (rc) | ||
779 | device_unregister(&ofdev->dev); | ||
699 | 780 | ||
700 | return 0; | 781 | return rc; |
701 | } | 782 | } |
702 | 783 | ||
703 | void of_device_unregister(struct of_device *ofdev) | 784 | void of_device_unregister(struct of_device *ofdev) |
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 4b06dcb00ebd..4ca9e5fc97f4 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c | |||
@@ -444,6 +444,7 @@ static struct property * __init build_one_prop(phandle node, char *prev, char *s | |||
444 | static struct property *tmp = NULL; | 444 | static struct property *tmp = NULL; |
445 | struct property *p; | 445 | struct property *p; |
446 | int len; | 446 | int len; |
447 | const char *name; | ||
447 | 448 | ||
448 | if (tmp) { | 449 | if (tmp) { |
449 | p = tmp; | 450 | p = tmp; |
@@ -456,19 +457,21 @@ static struct property * __init build_one_prop(phandle node, char *prev, char *s | |||
456 | 457 | ||
457 | p->name = (char *) (p + 1); | 458 | p->name = (char *) (p + 1); |
458 | if (special_name) { | 459 | if (special_name) { |
460 | strcpy(p->name, special_name); | ||
459 | p->length = special_len; | 461 | p->length = special_len; |
460 | p->value = prom_early_alloc(special_len); | 462 | p->value = prom_early_alloc(special_len); |
461 | memcpy(p->value, special_val, special_len); | 463 | memcpy(p->value, special_val, special_len); |
462 | } else { | 464 | } else { |
463 | if (prev == NULL) { | 465 | if (prev == NULL) { |
464 | prom_firstprop(node, p->name); | 466 | name = prom_firstprop(node, NULL); |
465 | } else { | 467 | } else { |
466 | prom_nextprop(node, prev, p->name); | 468 | name = prom_nextprop(node, prev, NULL); |
467 | } | 469 | } |
468 | if (strlen(p->name) == 0) { | 470 | if (strlen(name) == 0) { |
469 | tmp = p; | 471 | tmp = p; |
470 | return NULL; | 472 | return NULL; |
471 | } | 473 | } |
474 | strcpy(p->name, name); | ||
472 | p->length = prom_getproplen(node, p->name); | 475 | p->length = prom_getproplen(node, p->name); |
473 | if (p->length <= 0) { | 476 | if (p->length <= 0) { |
474 | p->length = 0; | 477 | p->length = 0; |
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 8606ef4e52e9..0251cab4708b 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <asm/smp.h> | 17 | #include <asm/smp.h> |
18 | #include <linux/user.h> | 18 | #include <linux/user.h> |
19 | #include <linux/a.out.h> | 19 | #include <linux/a.out.h> |
20 | #include <linux/tty.h> | 20 | #include <linux/screen_info.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
@@ -348,9 +348,9 @@ void __init setup_arch(char **cmdline_p) | |||
348 | init_mm.context = (unsigned long) NO_CONTEXT; | 348 | init_mm.context = (unsigned long) NO_CONTEXT; |
349 | init_task.thread.kregs = &fake_swapper_regs; | 349 | init_task.thread.kregs = &fake_swapper_regs; |
350 | 350 | ||
351 | smp_setup_cpu_possible_map(); | ||
352 | |||
353 | paging_init(); | 351 | paging_init(); |
352 | |||
353 | smp_setup_cpu_possible_map(); | ||
354 | } | 354 | } |
355 | 355 | ||
356 | static int __init set_preferred_console(void) | 356 | static int __init set_preferred_console(void) |
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 6135d4faeeeb..276f22881d0f 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <asm/tlbflush.h> | 34 | #include <asm/tlbflush.h> |
35 | #include <asm/cpudata.h> | 35 | #include <asm/cpudata.h> |
36 | 36 | ||
37 | volatile int smp_processors_ready = 0; | ||
38 | int smp_num_cpus = 1; | 37 | int smp_num_cpus = 1; |
39 | volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,}; | 38 | volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,}; |
40 | unsigned char boot_cpu_id = 0; | 39 | unsigned char boot_cpu_id = 0; |
@@ -87,6 +86,7 @@ void __cpuinit smp_store_cpu_info(int id) | |||
87 | void __init smp_cpus_done(unsigned int max_cpus) | 86 | void __init smp_cpus_done(unsigned int max_cpus) |
88 | { | 87 | { |
89 | extern void smp4m_smp_done(void); | 88 | extern void smp4m_smp_done(void); |
89 | extern void smp4d_smp_done(void); | ||
90 | unsigned long bogosum = 0; | 90 | unsigned long bogosum = 0; |
91 | int cpu, num; | 91 | int cpu, num; |
92 | 92 | ||
@@ -100,8 +100,34 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
100 | num, bogosum/(500000/HZ), | 100 | num, bogosum/(500000/HZ), |
101 | (bogosum/(5000/HZ))%100); | 101 | (bogosum/(5000/HZ))%100); |
102 | 102 | ||
103 | BUG_ON(sparc_cpu_model != sun4m); | 103 | switch(sparc_cpu_model) { |
104 | smp4m_smp_done(); | 104 | case sun4: |
105 | printk("SUN4\n"); | ||
106 | BUG(); | ||
107 | break; | ||
108 | case sun4c: | ||
109 | printk("SUN4C\n"); | ||
110 | BUG(); | ||
111 | break; | ||
112 | case sun4m: | ||
113 | smp4m_smp_done(); | ||
114 | break; | ||
115 | case sun4d: | ||
116 | smp4d_smp_done(); | ||
117 | break; | ||
118 | case sun4e: | ||
119 | printk("SUN4E\n"); | ||
120 | BUG(); | ||
121 | break; | ||
122 | case sun4u: | ||
123 | printk("SUN4U\n"); | ||
124 | BUG(); | ||
125 | break; | ||
126 | default: | ||
127 | printk("UNKNOWN!\n"); | ||
128 | BUG(); | ||
129 | break; | ||
130 | }; | ||
105 | } | 131 | } |
106 | 132 | ||
107 | void cpu_panic(void) | 133 | void cpu_panic(void) |
@@ -267,9 +293,9 @@ int setup_profiling_timer(unsigned int multiplier) | |||
267 | void __init smp_prepare_cpus(unsigned int max_cpus) | 293 | void __init smp_prepare_cpus(unsigned int max_cpus) |
268 | { | 294 | { |
269 | extern void smp4m_boot_cpus(void); | 295 | extern void smp4m_boot_cpus(void); |
296 | extern void smp4d_boot_cpus(void); | ||
270 | int i, cpuid, extra; | 297 | int i, cpuid, extra; |
271 | 298 | ||
272 | BUG_ON(sparc_cpu_model != sun4m); | ||
273 | printk("Entering SMP Mode...\n"); | 299 | printk("Entering SMP Mode...\n"); |
274 | 300 | ||
275 | extra = 0; | 301 | extra = 0; |
@@ -283,7 +309,34 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
283 | 309 | ||
284 | smp_store_cpu_info(boot_cpu_id); | 310 | smp_store_cpu_info(boot_cpu_id); |
285 | 311 | ||
286 | smp4m_boot_cpus(); | 312 | switch(sparc_cpu_model) { |
313 | case sun4: | ||
314 | printk("SUN4\n"); | ||
315 | BUG(); | ||
316 | break; | ||
317 | case sun4c: | ||
318 | printk("SUN4C\n"); | ||
319 | BUG(); | ||
320 | break; | ||
321 | case sun4m: | ||
322 | smp4m_boot_cpus(); | ||
323 | break; | ||
324 | case sun4d: | ||
325 | smp4d_boot_cpus(); | ||
326 | break; | ||
327 | case sun4e: | ||
328 | printk("SUN4E\n"); | ||
329 | BUG(); | ||
330 | break; | ||
331 | case sun4u: | ||
332 | printk("SUN4U\n"); | ||
333 | BUG(); | ||
334 | break; | ||
335 | default: | ||
336 | printk("UNKNOWN!\n"); | ||
337 | BUG(); | ||
338 | break; | ||
339 | }; | ||
287 | } | 340 | } |
288 | 341 | ||
289 | /* Set this up early so that things like the scheduler can init | 342 | /* Set this up early so that things like the scheduler can init |
@@ -323,9 +376,37 @@ void __init smp_prepare_boot_cpu(void) | |||
323 | int __cpuinit __cpu_up(unsigned int cpu) | 376 | int __cpuinit __cpu_up(unsigned int cpu) |
324 | { | 377 | { |
325 | extern int smp4m_boot_one_cpu(int); | 378 | extern int smp4m_boot_one_cpu(int); |
326 | int ret; | 379 | extern int smp4d_boot_one_cpu(int); |
327 | 380 | int ret=0; | |
328 | ret = smp4m_boot_one_cpu(cpu); | 381 | |
382 | switch(sparc_cpu_model) { | ||
383 | case sun4: | ||
384 | printk("SUN4\n"); | ||
385 | BUG(); | ||
386 | break; | ||
387 | case sun4c: | ||
388 | printk("SUN4C\n"); | ||
389 | BUG(); | ||
390 | break; | ||
391 | case sun4m: | ||
392 | ret = smp4m_boot_one_cpu(cpu); | ||
393 | break; | ||
394 | case sun4d: | ||
395 | ret = smp4d_boot_one_cpu(cpu); | ||
396 | break; | ||
397 | case sun4e: | ||
398 | printk("SUN4E\n"); | ||
399 | BUG(); | ||
400 | break; | ||
401 | case sun4u: | ||
402 | printk("SUN4U\n"); | ||
403 | BUG(); | ||
404 | break; | ||
405 | default: | ||
406 | printk("UNKNOWN!\n"); | ||
407 | BUG(); | ||
408 | break; | ||
409 | }; | ||
329 | 410 | ||
330 | if (!ret) { | 411 | if (!ret) { |
331 | cpu_set(cpu, smp_commenced_mask); | 412 | cpu_set(cpu, smp_commenced_mask); |
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 5fb987fc3d63..4d441a554d35 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c | |||
@@ -237,7 +237,6 @@ EXPORT_SYMBOL(prom_node_has_property); | |||
237 | EXPORT_SYMBOL(prom_setprop); | 237 | EXPORT_SYMBOL(prom_setprop); |
238 | EXPORT_SYMBOL(saved_command_line); | 238 | EXPORT_SYMBOL(saved_command_line); |
239 | EXPORT_SYMBOL(prom_apply_obio_ranges); | 239 | EXPORT_SYMBOL(prom_apply_obio_ranges); |
240 | EXPORT_SYMBOL(prom_getname); | ||
241 | EXPORT_SYMBOL(prom_feval); | 240 | EXPORT_SYMBOL(prom_feval); |
242 | EXPORT_SYMBOL(prom_getbool); | 241 | EXPORT_SYMBOL(prom_getbool); |
243 | EXPORT_SYMBOL(prom_getstring); | 242 | EXPORT_SYMBOL(prom_getstring); |
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index b141b7ee6717..3ff4edd32815 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c | |||
@@ -42,16 +42,11 @@ extern ctxd_t *srmmu_ctx_table_phys; | |||
42 | 42 | ||
43 | extern void calibrate_delay(void); | 43 | extern void calibrate_delay(void); |
44 | 44 | ||
45 | extern volatile int smp_processors_ready; | 45 | static volatile int smp_processors_ready = 0; |
46 | extern int smp_num_cpus; | ||
47 | static int smp_highest_cpu; | 46 | static int smp_highest_cpu; |
48 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; | 47 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; |
49 | extern cpuinfo_sparc cpu_data[NR_CPUS]; | 48 | extern cpuinfo_sparc cpu_data[NR_CPUS]; |
50 | extern unsigned char boot_cpu_id; | 49 | extern unsigned char boot_cpu_id; |
51 | extern int smp_activated; | ||
52 | extern volatile int __cpu_number_map[NR_CPUS]; | ||
53 | extern volatile int __cpu_logical_map[NR_CPUS]; | ||
54 | extern volatile unsigned long ipi_count; | ||
55 | extern volatile int smp_process_available; | 50 | extern volatile int smp_process_available; |
56 | 51 | ||
57 | extern cpumask_t smp_commenced_mask; | 52 | extern cpumask_t smp_commenced_mask; |
@@ -144,6 +139,8 @@ void __init smp4d_callin(void) | |||
144 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 139 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
145 | cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */ | 140 | cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */ |
146 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); | 141 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); |
142 | cpu_set(cpuid, cpu_online_map); | ||
143 | |||
147 | } | 144 | } |
148 | 145 | ||
149 | extern void init_IRQ(void); | 146 | extern void init_IRQ(void); |
@@ -160,51 +157,24 @@ extern unsigned long trapbase_cpu3[]; | |||
160 | 157 | ||
161 | void __init smp4d_boot_cpus(void) | 158 | void __init smp4d_boot_cpus(void) |
162 | { | 159 | { |
163 | int cpucount = 0; | ||
164 | int i, mid; | ||
165 | |||
166 | printk("Entering SMP Mode...\n"); | ||
167 | |||
168 | if (boot_cpu_id) | 160 | if (boot_cpu_id) |
169 | current_set[0] = NULL; | 161 | current_set[0] = NULL; |
170 | |||
171 | local_irq_enable(); | ||
172 | cpus_clear(cpu_present_map); | ||
173 | |||
174 | /* XXX This whole thing has to go. See sparc64. */ | ||
175 | for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) | ||
176 | cpu_set(mid, cpu_present_map); | ||
177 | SMP_PRINTK(("cpu_present_map %08lx\n", cpus_addr(cpu_present_map)[0])); | ||
178 | for(i=0; i < NR_CPUS; i++) | ||
179 | __cpu_number_map[i] = -1; | ||
180 | for(i=0; i < NR_CPUS; i++) | ||
181 | __cpu_logical_map[i] = -1; | ||
182 | __cpu_number_map[boot_cpu_id] = 0; | ||
183 | __cpu_logical_map[0] = boot_cpu_id; | ||
184 | current_thread_info()->cpu = boot_cpu_id; | ||
185 | smp_store_cpu_info(boot_cpu_id); | ||
186 | smp_setup_percpu_timer(); | 162 | smp_setup_percpu_timer(); |
187 | local_flush_cache_all(); | 163 | local_flush_cache_all(); |
188 | if (cpu_find_by_instance(1, NULL, NULL)) | 164 | } |
189 | return; /* Not an MP box. */ | 165 | |
190 | SMP_PRINTK(("Iterating over CPUs\n")); | 166 | int smp4d_boot_one_cpu(int i) |
191 | for(i = 0; i < NR_CPUS; i++) { | 167 | { |
192 | if(i == boot_cpu_id) | ||
193 | continue; | ||
194 | |||
195 | if (cpu_isset(i, cpu_present_map)) { | ||
196 | extern unsigned long sun4d_cpu_startup; | 168 | extern unsigned long sun4d_cpu_startup; |
197 | unsigned long *entry = &sun4d_cpu_startup; | 169 | unsigned long *entry = &sun4d_cpu_startup; |
198 | struct task_struct *p; | 170 | struct task_struct *p; |
199 | int timeout; | 171 | int timeout; |
200 | int no; | 172 | int cpu_node; |
201 | 173 | ||
174 | cpu_find_by_instance(i, &cpu_node,NULL); | ||
202 | /* Cook up an idler for this guy. */ | 175 | /* Cook up an idler for this guy. */ |
203 | p = fork_idle(i); | 176 | p = fork_idle(i); |
204 | cpucount++; | ||
205 | current_set[i] = task_thread_info(p); | 177 | current_set[i] = task_thread_info(p); |
206 | for (no = 0; !cpu_find_by_instance(no, NULL, &mid) | ||
207 | && mid != i; no++) ; | ||
208 | 178 | ||
209 | /* | 179 | /* |
210 | * Initialize the contexts table | 180 | * Initialize the contexts table |
@@ -216,9 +186,9 @@ void __init smp4d_boot_cpus(void) | |||
216 | smp_penguin_ctable.reg_size = 0; | 186 | smp_penguin_ctable.reg_size = 0; |
217 | 187 | ||
218 | /* whirrr, whirrr, whirrrrrrrrr... */ | 188 | /* whirrr, whirrr, whirrrrrrrrr... */ |
219 | SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, cpu_data(no).prom_node)); | 189 | SMP_PRINTK(("Starting CPU %d at %p \n", i, entry)); |
220 | local_flush_cache_all(); | 190 | local_flush_cache_all(); |
221 | prom_startcpu(cpu_data(no).prom_node, | 191 | prom_startcpu(cpu_node, |
222 | &smp_penguin_ctable, 0, (char *)entry); | 192 | &smp_penguin_ctable, 0, (char *)entry); |
223 | 193 | ||
224 | SMP_PRINTK(("prom_startcpu returned :)\n")); | 194 | SMP_PRINTK(("prom_startcpu returned :)\n")); |
@@ -230,39 +200,30 @@ void __init smp4d_boot_cpus(void) | |||
230 | udelay(200); | 200 | udelay(200); |
231 | } | 201 | } |
232 | 202 | ||
233 | if(cpu_callin_map[i]) { | 203 | if (!(cpu_callin_map[i])) { |
234 | /* Another "Red Snapper". */ | 204 | printk("Processor %d is stuck.\n", i); |
235 | __cpu_number_map[i] = cpucount; | 205 | return -ENODEV; |
236 | __cpu_logical_map[cpucount] = i; | 206 | |
237 | } else { | ||
238 | cpucount--; | ||
239 | printk("Processor %d is stuck.\n", i); | ||
240 | } | ||
241 | } | ||
242 | if(!(cpu_callin_map[i])) { | ||
243 | cpu_clear(i, cpu_present_map); | ||
244 | __cpu_number_map[i] = -1; | ||
245 | } | ||
246 | } | 207 | } |
247 | local_flush_cache_all(); | 208 | local_flush_cache_all(); |
248 | if(cpucount == 0) { | 209 | return 0; |
249 | printk("Error: only one Processor found.\n"); | 210 | } |
250 | cpu_present_map = cpumask_of_cpu(hard_smp4d_processor_id()); | 211 | |
251 | } else { | 212 | void __init smp4d_smp_done(void) |
252 | unsigned long bogosum = 0; | 213 | { |
253 | 214 | int i, first; | |
254 | for_each_present_cpu(i) { | 215 | int *prev; |
255 | bogosum += cpu_data(i).udelay_val; | 216 | |
256 | smp_highest_cpu = i; | 217 | /* setup cpu list for irq rotation */ |
218 | first = 0; | ||
219 | prev = &first; | ||
220 | for (i = 0; i < NR_CPUS; i++) | ||
221 | if (cpu_online(i)) { | ||
222 | *prev = i; | ||
223 | prev = &cpu_data(i).next; | ||
257 | } | 224 | } |
258 | SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100)); | 225 | *prev = first; |
259 | printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", | 226 | local_flush_cache_all(); |
260 | cpucount + 1, | ||
261 | bogosum/(500000/HZ), | ||
262 | (bogosum/(5000/HZ))%100); | ||
263 | smp_activated = 1; | ||
264 | smp_num_cpus = cpucount + 1; | ||
265 | } | ||
266 | 227 | ||
267 | /* Free unneeded trap tables */ | 228 | /* Free unneeded trap tables */ |
268 | ClearPageReserved(virt_to_page(trapbase_cpu1)); | 229 | ClearPageReserved(virt_to_page(trapbase_cpu1)); |
@@ -334,7 +295,7 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, | |||
334 | register int i; | 295 | register int i; |
335 | 296 | ||
336 | mask = cpumask_of_cpu(hard_smp4d_processor_id()); | 297 | mask = cpumask_of_cpu(hard_smp4d_processor_id()); |
337 | cpus_andnot(mask, cpu_present_map, mask); | 298 | cpus_andnot(mask, cpu_online_map, mask); |
338 | for(i = 0; i <= high; i++) { | 299 | for(i = 0; i <= high; i++) { |
339 | if (cpu_isset(i, mask)) { | 300 | if (cpu_isset(i, mask)) { |
340 | ccall_info.processors_in[i] = 0; | 301 | ccall_info.processors_in[i] = 0; |
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 3b32096134aa..7d4a649138f6 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c | |||
@@ -39,7 +39,6 @@ extern ctxd_t *srmmu_ctx_table_phys; | |||
39 | 39 | ||
40 | extern void calibrate_delay(void); | 40 | extern void calibrate_delay(void); |
41 | 41 | ||
42 | extern volatile int smp_processors_ready; | ||
43 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; | 42 | extern volatile unsigned long cpu_callin_map[NR_CPUS]; |
44 | extern unsigned char boot_cpu_id; | 43 | extern unsigned char boot_cpu_id; |
45 | 44 | ||
@@ -217,7 +216,6 @@ void __init smp4m_smp_done(void) | |||
217 | } | 216 | } |
218 | 217 | ||
219 | /* Ok, they are spinning and ready to go. */ | 218 | /* Ok, they are spinning and ready to go. */ |
220 | smp_processors_ready = 1; | ||
221 | } | 219 | } |
222 | 220 | ||
223 | /* At each hardware IRQ, we get this called to forward IRQ reception | 221 | /* At each hardware IRQ, we get this called to forward IRQ reception |
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 0cdfc9d294b4..896863fb208a 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c | |||
@@ -219,6 +219,21 @@ out: | |||
219 | return err; | 219 | return err; |
220 | } | 220 | } |
221 | 221 | ||
222 | int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) | ||
223 | { | ||
224 | if (ARCH_SUN4C_SUN4 && | ||
225 | (len > 0x20000000 || | ||
226 | ((flags & MAP_FIXED) && | ||
227 | addr < 0xe0000000 && addr + len > 0x20000000))) | ||
228 | return -EINVAL; | ||
229 | |||
230 | /* See asm-sparc/uaccess.h */ | ||
231 | if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) | ||
232 | return -EINVAL; | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
222 | /* Linux version of mmap */ | 237 | /* Linux version of mmap */ |
223 | static unsigned long do_mmap2(unsigned long addr, unsigned long len, | 238 | static unsigned long do_mmap2(unsigned long addr, unsigned long len, |
224 | unsigned long prot, unsigned long flags, unsigned long fd, | 239 | unsigned long prot, unsigned long flags, unsigned long fd, |
@@ -233,25 +248,13 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len, | |||
233 | goto out; | 248 | goto out; |
234 | } | 249 | } |
235 | 250 | ||
236 | retval = -EINVAL; | ||
237 | len = PAGE_ALIGN(len); | 251 | len = PAGE_ALIGN(len); |
238 | if (ARCH_SUN4C_SUN4 && | ||
239 | (len > 0x20000000 || | ||
240 | ((flags & MAP_FIXED) && | ||
241 | addr < 0xe0000000 && addr + len > 0x20000000))) | ||
242 | goto out_putf; | ||
243 | |||
244 | /* See asm-sparc/uaccess.h */ | ||
245 | if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) | ||
246 | goto out_putf; | ||
247 | |||
248 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | 252 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); |
249 | 253 | ||
250 | down_write(¤t->mm->mmap_sem); | 254 | down_write(¤t->mm->mmap_sem); |
251 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | 255 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); |
252 | up_write(¤t->mm->mmap_sem); | 256 | up_write(¤t->mm->mmap_sem); |
253 | 257 | ||
254 | out_putf: | ||
255 | if (file) | 258 | if (file) |
256 | fput(file); | 259 | fput(file); |
257 | out: | 260 | out: |
@@ -465,21 +468,23 @@ sys_rt_sigaction(int sig, | |||
465 | 468 | ||
466 | asmlinkage int sys_getdomainname(char __user *name, int len) | 469 | asmlinkage int sys_getdomainname(char __user *name, int len) |
467 | { | 470 | { |
468 | int nlen; | 471 | int nlen, err; |
469 | int err = -EFAULT; | ||
470 | 472 | ||
473 | if (len < 0) | ||
474 | return -EINVAL; | ||
475 | |||
471 | down_read(&uts_sem); | 476 | down_read(&uts_sem); |
472 | 477 | ||
473 | nlen = strlen(system_utsname.domainname) + 1; | 478 | nlen = strlen(system_utsname.domainname) + 1; |
479 | err = -EINVAL; | ||
480 | if (nlen > len) | ||
481 | goto out; | ||
482 | |||
483 | err = -EFAULT; | ||
484 | if (!copy_to_user(name, system_utsname.domainname, nlen)) | ||
485 | err = 0; | ||
474 | 486 | ||
475 | if (nlen < len) | 487 | out: |
476 | len = nlen; | ||
477 | if (len > __NEW_UTS_LEN) | ||
478 | goto done; | ||
479 | if (copy_to_user(name, system_utsname.domainname, len)) | ||
480 | goto done; | ||
481 | err = 0; | ||
482 | done: | ||
483 | up_read(&uts_sem); | 488 | up_read(&uts_sem); |
484 | return err; | 489 | return err; |
485 | } | 490 | } |
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 04eb1eab6e3e..845081b01267 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c | |||
@@ -225,6 +225,32 @@ static __inline__ int has_low_battery(void) | |||
225 | return (data1 == data2); /* Was the write blocked? */ | 225 | return (data1 == data2); /* Was the write blocked? */ |
226 | } | 226 | } |
227 | 227 | ||
228 | static void __init mostek_set_system_time(void) | ||
229 | { | ||
230 | unsigned int year, mon, day, hour, min, sec; | ||
231 | struct mostek48t02 *mregs; | ||
232 | |||
233 | mregs = (struct mostek48t02 *)mstk48t02_regs; | ||
234 | if(!mregs) { | ||
235 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | ||
236 | prom_halt(); | ||
237 | } | ||
238 | spin_lock_irq(&mostek_lock); | ||
239 | mregs->creg |= MSTK_CREG_READ; | ||
240 | sec = MSTK_REG_SEC(mregs); | ||
241 | min = MSTK_REG_MIN(mregs); | ||
242 | hour = MSTK_REG_HOUR(mregs); | ||
243 | day = MSTK_REG_DOM(mregs); | ||
244 | mon = MSTK_REG_MONTH(mregs); | ||
245 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); | ||
246 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
247 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
248 | set_normalized_timespec(&wall_to_monotonic, | ||
249 | -xtime.tv_sec, -xtime.tv_nsec); | ||
250 | mregs->creg &= ~MSTK_CREG_READ; | ||
251 | spin_unlock_irq(&mostek_lock); | ||
252 | } | ||
253 | |||
228 | /* Probe for the real time clock chip on Sun4 */ | 254 | /* Probe for the real time clock chip on Sun4 */ |
229 | static __inline__ void sun4_clock_probe(void) | 255 | static __inline__ void sun4_clock_probe(void) |
230 | { | 256 | { |
@@ -273,6 +299,7 @@ static __inline__ void sun4_clock_probe(void) | |||
273 | #endif | 299 | #endif |
274 | } | 300 | } |
275 | 301 | ||
302 | #ifndef CONFIG_SUN4 | ||
276 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) | 303 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) |
277 | { | 304 | { |
278 | struct device_node *dp = op->node; | 305 | struct device_node *dp = op->node; |
@@ -307,6 +334,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id | |||
307 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | 334 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) |
308 | kick_start_clock(); | 335 | kick_start_clock(); |
309 | 336 | ||
337 | mostek_set_system_time(); | ||
338 | |||
310 | return 0; | 339 | return 0; |
311 | } | 340 | } |
312 | 341 | ||
@@ -325,56 +354,37 @@ static struct of_platform_driver clock_driver = { | |||
325 | 354 | ||
326 | 355 | ||
327 | /* Probe for the mostek real time clock chip. */ | 356 | /* Probe for the mostek real time clock chip. */ |
328 | static void clock_init(void) | 357 | static int __init clock_init(void) |
329 | { | 358 | { |
330 | of_register_driver(&clock_driver, &of_bus_type); | 359 | return of_register_driver(&clock_driver, &of_bus_type); |
331 | } | 360 | } |
332 | 361 | ||
362 | /* Must be after subsys_initcall() so that busses are probed. Must | ||
363 | * be before device_initcall() because things like the RTC driver | ||
364 | * need to see the clock registers. | ||
365 | */ | ||
366 | fs_initcall(clock_init); | ||
367 | #endif /* !CONFIG_SUN4 */ | ||
368 | |||
333 | void __init sbus_time_init(void) | 369 | void __init sbus_time_init(void) |
334 | { | 370 | { |
335 | unsigned int year, mon, day, hour, min, sec; | ||
336 | struct mostek48t02 *mregs; | ||
337 | |||
338 | #ifdef CONFIG_SUN4 | ||
339 | int temp; | ||
340 | struct intersil *iregs; | ||
341 | #endif | ||
342 | 371 | ||
343 | BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); | 372 | BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); |
344 | btfixup(); | 373 | btfixup(); |
345 | 374 | ||
346 | if (ARCH_SUN4) | 375 | if (ARCH_SUN4) |
347 | sun4_clock_probe(); | 376 | sun4_clock_probe(); |
348 | else | ||
349 | clock_init(); | ||
350 | 377 | ||
351 | sparc_init_timers(timer_interrupt); | 378 | sparc_init_timers(timer_interrupt); |
352 | 379 | ||
353 | #ifdef CONFIG_SUN4 | 380 | #ifdef CONFIG_SUN4 |
354 | if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { | 381 | if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { |
355 | #endif | 382 | mostek_set_system_time(); |
356 | mregs = (struct mostek48t02 *)mstk48t02_regs; | ||
357 | if(!mregs) { | ||
358 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | ||
359 | prom_halt(); | ||
360 | } | ||
361 | spin_lock_irq(&mostek_lock); | ||
362 | mregs->creg |= MSTK_CREG_READ; | ||
363 | sec = MSTK_REG_SEC(mregs); | ||
364 | min = MSTK_REG_MIN(mregs); | ||
365 | hour = MSTK_REG_HOUR(mregs); | ||
366 | day = MSTK_REG_DOM(mregs); | ||
367 | mon = MSTK_REG_MONTH(mregs); | ||
368 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); | ||
369 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
370 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
371 | set_normalized_timespec(&wall_to_monotonic, | ||
372 | -xtime.tv_sec, -xtime.tv_nsec); | ||
373 | mregs->creg &= ~MSTK_CREG_READ; | ||
374 | spin_unlock_irq(&mostek_lock); | ||
375 | #ifdef CONFIG_SUN4 | ||
376 | } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { | 383 | } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { |
377 | /* initialise the intersil on sun4 */ | 384 | /* initialise the intersil on sun4 */ |
385 | unsigned int year, mon, day, hour, min, sec; | ||
386 | int temp; | ||
387 | struct intersil *iregs; | ||
378 | 388 | ||
379 | iregs=intersil_clock; | 389 | iregs=intersil_clock; |
380 | if(!iregs) { | 390 | if(!iregs) { |
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 42c1c700c0a7..2bb1309003dd 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c | |||
@@ -64,6 +64,7 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) | |||
64 | 64 | ||
65 | sbus->iommu = (struct iommu_struct *)iounit; | 65 | sbus->iommu = (struct iommu_struct *)iounit; |
66 | iounit->page_table = xpt; | 66 | iounit->page_table = xpt; |
67 | spin_lock_init(&iounit->lock); | ||
67 | 68 | ||
68 | for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t); | 69 | for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t); |
69 | xpt < xptend;) | 70 | xpt < xptend;) |
diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree.c index 2bf03ee8cde5..5ec246573a98 100644 --- a/arch/sparc/prom/tree.c +++ b/arch/sparc/prom/tree.c | |||
@@ -205,24 +205,6 @@ int prom_searchsiblings(int node_start, char *nodename) | |||
205 | return 0; | 205 | return 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | /* Gets name in the form prom v2+ uses it (name@x,yyyyy or name (if no reg)) */ | ||
209 | int prom_getname (int node, char *buffer, int len) | ||
210 | { | ||
211 | int i; | ||
212 | struct linux_prom_registers reg[PROMREG_MAX]; | ||
213 | |||
214 | i = prom_getproperty (node, "name", buffer, len); | ||
215 | if (i <= 0) return -1; | ||
216 | buffer [i] = 0; | ||
217 | len -= i; | ||
218 | i = prom_getproperty (node, "reg", (char *)reg, sizeof (reg)); | ||
219 | if (i <= 0) return 0; | ||
220 | if (len < 11) return -1; | ||
221 | buffer = strchr (buffer, 0); | ||
222 | sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | /* Interal version of nextprop that does not alter return values. */ | 208 | /* Interal version of nextprop that does not alter return values. */ |
227 | char * __prom_nextprop(int node, char * oprop) | 209 | char * __prom_nextprop(int node, char * oprop) |
228 | { | 210 | { |