From 894673ee6122a3ce1958e1fe096901ba5356a96b Mon Sep 17 00:00:00 2001 From: Jon Smirl Date: Mon, 10 Jul 2006 04:44:13 -0700 Subject: [PATCH] tty: Remove include of screen_info.h from tty.h screen_info.h doesn't have anything to do with the tty layer and shouldn't be included by tty.h. This patches removes the include and modifies all users to directly include screen_info.h. struct screen_info is mainly used to communicate with the console drivers in drivers/video/console. Note that this patch touches every arch and I have no way of testing it. If there is a mistake the worst thing that will happen is a compile error. [akpm@osdl.org: fix arm build] [akpm@osdl.org: fix alpha build] Signed-off-by: Jon Smirl Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sparc/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 8606ef4e52e..35488d6c745 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3-70-g09d2 From 6cc8b6f51eb1af72882c279f691c5de7d5a43bf2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Jul 2006 15:28:54 -0700 Subject: [SPARC64]: of_device_register() error checking fix device_create_file() can fail. This causes the sparc64 compile to fail when my fanatical __must_check patch is applied, due to -Werror. [ Added necessary identical fix for sparc32. -DaveM] Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device.c | 6 ++++-- arch/sparc64/kernel/of_device.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index bc956c53037..bbd3203b86a 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -695,9 +695,11 @@ int of_device_register(struct of_device *ofdev) if (rc) return rc; - device_create_file(&ofdev->dev, &dev_attr_devspec); + rc = device_create_file(&ofdev->dev, &dev_attr_devspec); + if (rc) + device_unregister(&ofdev->dev); - return 0; + return rc; } void of_device_unregister(struct of_device *ofdev) diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 169b017eec0..8e177a0abc1 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -922,9 +922,11 @@ int of_device_register(struct of_device *ofdev) if (rc) return rc; - device_create_file(&ofdev->dev, &dev_attr_devspec); + rc = device_create_file(&ofdev->dev, &dev_attr_devspec); + if (rc) + device_unregister(&ofdev->dev); - return 0; + return rc; } void of_device_unregister(struct of_device *ofdev) -- cgit v1.2.3-70-g09d2 From a83f982313bc60dd3d87e50f8c88d6a169e8a5a0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 12 Jul 2006 23:19:31 -0700 Subject: [SPARC]: Fix OF register translations under sub-PCI busses. There is an implicit assumption in the code that ranges will translate to something that can fit in 2 32-bit cells, or a 64-bit value. For certain kinds of things below PCI this isn't necessarily true. Here is what the relevant OF device hierarchy looks like for one of the serial controllers on an Ultra5: Node 0xf005f1e0 ranges: 00000000.00000000.00000000.000001fe.01000000.00000000.01000000 01000000.00000000.00000000.000001fe.02000000.00000000.01000000 02000000.00000000.00000000.000001ff.00000000.00000001.00000000 03000000.00000000.00000000.000001ff.00000000.00000001.00000000 device_type: 'pci' model: 'SUNW,sabre' Node 0xf005f9d4 device_type: 'pci' model: 'SUNW,simba' Node 0xf0060d24 ranges: 00000010.00000000 82010810.00000000.f0000000 01000000 00000014.00000000 82010814.00000000.f1000000 00800000 name: 'ebus' Node 0xf0062dac reg: 00000014.003083f8.00000008 --> 0x1ff.f13083f8 device_type: 'serial' name: 'su' So the correct translation here is: 1) Match "su" register to second ranges entry of 'ebus', which translates into a PCI triplet "82010814.00000000.f1000000" of size 00800000, which gives us "82010814.00000000.f13083f8". 2) Pass-through "SUNW,simba" since it lacks ranges property 3) Match "82010814.00000000.f13083f8" to third ranges property of PCI controller node 'SUNW,sabre', and we arrive at the final physical MMIO address of "0x1fff13083f8". Due to the 2-cell assumption, we couldn't translate to a PCI 3-cell value, and we couldn't perform a pass-thru on it either. It was easiest to just stop splitting the ranges application operation between two methods, ->map and ->translate, and just let ->map do all the work. That way it would work purely on 32-bit cell arrays instead of having to "return" some value like a u64. It's still not %100 correct because the out-of-range check is still done using the 64 least significant bits of the range and address. But it does work for all the cases I've thrown at it so far. Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device.c | 167 ++++++++++++++-------- arch/sparc64/kernel/of_device.c | 308 +++++++++++++++++++++------------------- 2 files changed, 271 insertions(+), 204 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index bbd3203b86a..5a2faad5d04 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 = { }; EXPORT_SYMBOL(of_bus_type); -static inline u64 of_read_addr(u32 *cell, int size) +static inline u64 of_read_addr(const u32 *cell, int size) { u64 r = 0; while (size--) @@ -209,8 +209,8 @@ struct of_bus { int (*match)(struct device_node *parent); void (*count_cells)(struct device_node *child, int *addrc, int *sizec); - u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna); - int (*translate)(u32 *addr, u64 offset, int na); + int (*map)(u32 *addr, const u32 *range, + int na, int ns, int pna); unsigned int (*get_flags)(u32 *addr); }; @@ -224,27 +224,49 @@ static void of_bus_default_count_cells(struct device_node *dev, get_cells(dev, addrc, sizec); } -static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) +/* Make sure the least significant 64-bits are in-range. Even + * for 3 or 4 cell values it is a good enough approximation. + */ +static int of_out_of_range(const u32 *addr, const u32 *base, + const u32 *size, int na, int ns) { - u64 cp, s, da; + u64 a = of_read_addr(addr, na); + u64 b = of_read_addr(base, na); + + if (a < b) + return 1; - cp = of_read_addr(range, na); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr, na); + b += of_read_addr(size, ns); + if (a >= b) + return 1; - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; + return 0; } -static int of_bus_default_translate(u32 *addr, u64 offset, int na) +static int of_bus_default_map(u32 *addr, const u32 *range, + int na, int ns, int pna) { - u64 a = of_read_addr(addr, na); - memset(addr, 0, na * 4); - a += offset; - if (na > 1) - addr[na - 2] = a >> 32; - addr[na - 1] = a & 0xffffffffu; + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + if (ns > 2) { + printk("of_device: Cannot handle size cells (%d) > 2.", ns); + return -EINVAL; + } + + if (of_out_of_range(addr, range, range + na + pna, na, ns)) + return -EINVAL; + + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); + + /* Add in the child address offset. */ + for (i = 0; i < na; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); return 0; } @@ -254,14 +276,26 @@ static unsigned int of_bus_default_get_flags(u32 *addr) return IORESOURCE_MEM; } - /* * PCI bus specific translator */ static int of_bus_pci_match(struct device_node *np) { - return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex"); + if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + /* Do not do PCI specific frobbing if the + * PCI bridge lacks a ranges property. We + * want to pass it through up to the next + * parent as-is, not with the PCI translate + * method which chops off the top address cell. + */ + if (!of_find_property(np, "ranges", NULL)) + return 0; + + return 1; + } + + return 0; } 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, *sizec = 2; } -static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) +static int of_bus_pci_map(u32 *addr, const u32 *range, + int na, int ns, int pna) { - u64 cp, s, da; + u32 result[OF_MAX_ADDR_CELLS]; + int i; /* Check address type match */ if ((addr[0] ^ range[0]) & 0x03000000) - return OF_BAD_ADDR; + return -EINVAL; - /* Read address values, skipping high cell */ - cp = of_read_addr(range + 1, na - 1); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr + 1, na - 1); + if (of_out_of_range(addr + 1, range + 1, range + na + pna, + na - 1, ns)) + return -EINVAL; - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; -} + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); -static int of_bus_pci_translate(u32 *addr, u64 offset, int na) -{ - return of_bus_default_translate(addr + 1, offset, na - 1); + /* Add in the child address offset, skipping high cell. */ + for (i = 0; i < na - 1; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); + + return 0; } 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, *sizec = 1; } -static u64 of_bus_sbus_map(u32 *addr, u32 *range, int na, int ns, int pna) +static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) { return of_bus_default_map(addr, range, na, ns, pna); } -static int of_bus_sbus_translate(u32 *addr, u64 offset, int na) -{ - return of_bus_default_translate(addr, offset, na); -} - static unsigned int of_bus_sbus_get_flags(u32 *addr) { return IORESOURCE_MEM; @@ -360,7 +394,6 @@ static struct of_bus of_busses[] = { .match = of_bus_pci_match, .count_cells = of_bus_pci_count_cells, .map = of_bus_pci_map, - .translate = of_bus_pci_translate, .get_flags = of_bus_pci_get_flags, }, /* SBUS */ @@ -370,7 +403,6 @@ static struct of_bus of_busses[] = { .match = of_bus_sbus_match, .count_cells = of_bus_sbus_count_cells, .map = of_bus_sbus_map, - .translate = of_bus_sbus_translate, .get_flags = of_bus_sbus_get_flags, }, /* Default */ @@ -380,7 +412,6 @@ static struct of_bus of_busses[] = { .match = NULL, .count_cells = of_bus_default_count_cells, .map = of_bus_default_map, - .translate = of_bus_default_translate, .get_flags = of_bus_default_get_flags, }, }; @@ -405,33 +436,34 @@ static int __init build_one_resource(struct device_node *parent, u32 *ranges; unsigned int rlen; int rone; - u64 offset = OF_BAD_ADDR; ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { - offset = of_read_addr(addr, na); - memset(addr, 0, pna * 4); - goto finish; + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + memset(result, 0, pna * 4); + for (i = 0; i < na; i++) + result[pna - 1 - i] = + addr[na - 1 - i]; + + memcpy(addr, result, pna * 4); + return 0; } /* Now walk through the ranges */ rlen /= 4; rone = na + pna + ns; for (; rlen >= rone; rlen -= rone, ranges += rone) { - offset = bus->map(addr, ranges, na, ns, pna); - if (offset != OF_BAD_ADDR) - break; + if (!bus->map(addr, ranges, na, ns, pna)) + return 0; } - if (offset == OF_BAD_ADDR) - return 1; - - memcpy(addr, ranges + na, 4 * pna); -finish: - /* Translate it into parent bus space */ - return pbus->translate(addr, offset, pna); + return 1; } +static int of_resource_verbose; + static void __init build_device_resources(struct of_device *op, struct device *parent) { @@ -497,7 +529,8 @@ static void __init build_device_resources(struct of_device *op, pbus = of_match_bus(pp); pbus->count_cells(dp, &pna, &pns); - if (build_one_resource(dp, bus, pbus, addr, dna, dns, pna)) + if (build_one_resource(dp, bus, pbus, addr, + dna, dns, pna)) break; dna = pna; @@ -507,6 +540,12 @@ static void __init build_device_resources(struct of_device *op, build_res: memset(r, 0, sizeof(*r)); + + if (of_resource_verbose) + printk("%s reg[%d] -> %llx\n", + op->node->full_name, index, + result); + if (result != OF_BAD_ADDR) { r->start = result & 0xffffffff; r->end = result + size - 1; @@ -643,6 +682,18 @@ static int __init of_bus_driver_init(void) postcore_initcall(of_bus_driver_init); +static int __init of_debug(char *str) +{ + int val = 0; + + get_option(&str, &val); + if (val & 1) + of_resource_verbose = 1; + return 1; +} + +__setup("of_debug=", of_debug); + int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) { /* initialize common driver fields */ diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 8e177a0abc1..7064cee290a 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -210,7 +210,7 @@ struct bus_type of_bus_type = { }; EXPORT_SYMBOL(of_bus_type); -static inline u64 of_read_addr(u32 *cell, int size) +static inline u64 of_read_addr(const u32 *cell, int size) { u64 r = 0; while (size--) @@ -236,8 +236,8 @@ struct of_bus { int (*match)(struct device_node *parent); void (*count_cells)(struct device_node *child, int *addrc, int *sizec); - u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna); - int (*translate)(u32 *addr, u64 offset, int na); + int (*map)(u32 *addr, const u32 *range, + int na, int ns, int pna); unsigned int (*get_flags)(u32 *addr); }; @@ -251,27 +251,49 @@ static void of_bus_default_count_cells(struct device_node *dev, get_cells(dev, addrc, sizec); } -static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) +/* Make sure the least significant 64-bits are in-range. Even + * for 3 or 4 cell values it is a good enough approximation. + */ +static int of_out_of_range(const u32 *addr, const u32 *base, + const u32 *size, int na, int ns) { - u64 cp, s, da; + u64 a = of_read_addr(addr, na); + u64 b = of_read_addr(base, na); - cp = of_read_addr(range, na); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr, na); + if (a < b) + return 1; - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; + b += of_read_addr(size, ns); + if (a >= b) + return 1; + + return 0; } -static int of_bus_default_translate(u32 *addr, u64 offset, int na) +static int of_bus_default_map(u32 *addr, const u32 *range, + int na, int ns, int pna) { - u64 a = of_read_addr(addr, na); - memset(addr, 0, na * 4); - a += offset; - if (na > 1) - addr[na - 2] = a >> 32; - addr[na - 1] = a & 0xffffffffu; + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + if (ns > 2) { + printk("of_device: Cannot handle size cells (%d) > 2.", ns); + return -EINVAL; + } + + if (of_out_of_range(addr, range, range + na + pna, na, ns)) + return -EINVAL; + + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); + + /* Add in the child address offset. */ + for (i = 0; i < na; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); return 0; } @@ -287,7 +309,20 @@ static unsigned int of_bus_default_get_flags(u32 *addr) static int of_bus_pci_match(struct device_node *np) { - return !strcmp(np->type, "pci") || !strcmp(np->type, "pciex"); + if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + /* Do not do PCI specific frobbing if the + * PCI bridge lacks a ranges property. We + * want to pass it through up to the next + * parent as-is, not with the PCI translate + * method which chops off the top address cell. + */ + if (!of_find_property(np, "ranges", NULL)) + return 0; + + return 1; + } + + return 0; } static void of_bus_pci_count_cells(struct device_node *np, @@ -299,27 +334,32 @@ static void of_bus_pci_count_cells(struct device_node *np, *sizec = 2; } -static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) +static int of_bus_pci_map(u32 *addr, const u32 *range, + int na, int ns, int pna) { - u64 cp, s, da; + u32 result[OF_MAX_ADDR_CELLS]; + int i; /* Check address type match */ if ((addr[0] ^ range[0]) & 0x03000000) - return OF_BAD_ADDR; + return -EINVAL; - /* Read address values, skipping high cell */ - cp = of_read_addr(range + 1, na - 1); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr + 1, na - 1); + if (of_out_of_range(addr + 1, range + 1, range + na + pna, + na - 1, ns)) + return -EINVAL; - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; -} + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); -static int of_bus_pci_translate(u32 *addr, u64 offset, int na) -{ - return of_bus_default_translate(addr + 1, offset, na - 1); + /* Add in the child address offset, skipping high cell. */ + for (i = 0; i < na - 1; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); + + return 0; } static unsigned int of_bus_pci_get_flags(u32 *addr) @@ -339,59 +379,6 @@ static unsigned int of_bus_pci_get_flags(u32 *addr) return flags; } -/* - * ISA bus specific translator - */ - -static int of_bus_isa_match(struct device_node *np) -{ - return !strcmp(np->name, "isa"); -} - -static void of_bus_isa_count_cells(struct device_node *child, - int *addrc, int *sizec) -{ - if (addrc) - *addrc = 2; - if (sizec) - *sizec = 1; -} - -static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna) -{ - u64 cp, s, da; - - /* Check address type match */ - if ((addr[0] ^ range[0]) & 0x00000001) - return OF_BAD_ADDR; - - /* Read address values, skipping high cell */ - cp = of_read_addr(range + 1, na - 1); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr + 1, na - 1); - - if (da < cp || da >= (cp + s)) - return OF_BAD_ADDR; - return da - cp; -} - -static int of_bus_isa_translate(u32 *addr, u64 offset, int na) -{ - return of_bus_default_translate(addr + 1, offset, na - 1); -} - -static unsigned int of_bus_isa_get_flags(u32 *addr) -{ - unsigned int flags = 0; - u32 w = addr[0]; - - if (w & 1) - flags |= IORESOURCE_IO; - else - flags |= IORESOURCE_MEM; - return flags; -} - /* * SBUS bus specific translator */ @@ -411,16 +398,11 @@ static void of_bus_sbus_count_cells(struct device_node *child, *sizec = 1; } -static u64 of_bus_sbus_map(u32 *addr, u32 *range, int na, int ns, int pna) +static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) { return of_bus_default_map(addr, range, na, ns, pna); } -static int of_bus_sbus_translate(u32 *addr, u64 offset, int na) -{ - return of_bus_default_translate(addr, offset, na); -} - static unsigned int of_bus_sbus_get_flags(u32 *addr) { return IORESOURCE_MEM; @@ -439,19 +421,8 @@ static struct of_bus of_busses[] = { .match = of_bus_pci_match, .count_cells = of_bus_pci_count_cells, .map = of_bus_pci_map, - .translate = of_bus_pci_translate, .get_flags = of_bus_pci_get_flags, }, - /* ISA */ - { - .name = "isa", - .addr_prop_name = "reg", - .match = of_bus_isa_match, - .count_cells = of_bus_isa_count_cells, - .map = of_bus_isa_map, - .translate = of_bus_isa_translate, - .get_flags = of_bus_isa_get_flags, - }, /* SBUS */ { .name = "sbus", @@ -459,7 +430,6 @@ static struct of_bus of_busses[] = { .match = of_bus_sbus_match, .count_cells = of_bus_sbus_count_cells, .map = of_bus_sbus_map, - .translate = of_bus_sbus_translate, .get_flags = of_bus_sbus_get_flags, }, /* Default */ @@ -469,7 +439,6 @@ static struct of_bus of_busses[] = { .match = NULL, .count_cells = of_bus_default_count_cells, .map = of_bus_default_map, - .translate = of_bus_default_translate, .get_flags = of_bus_default_get_flags, }, }; @@ -494,33 +463,62 @@ static int __init build_one_resource(struct device_node *parent, u32 *ranges; unsigned int rlen; int rone; - u64 offset = OF_BAD_ADDR; ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { - offset = of_read_addr(addr, na); - memset(addr, 0, pna * 4); - goto finish; + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + memset(result, 0, pna * 4); + for (i = 0; i < na; i++) + result[pna - 1 - i] = + addr[na - 1 - i]; + + memcpy(addr, result, pna * 4); + return 0; } /* Now walk through the ranges */ rlen /= 4; rone = na + pna + ns; for (; rlen >= rone; rlen -= rone, ranges += rone) { - offset = bus->map(addr, ranges, na, ns, pna); - if (offset != OF_BAD_ADDR) - break; + if (!bus->map(addr, ranges, na, ns, pna)) + return 0; } - if (offset == OF_BAD_ADDR) + + return 1; +} + +static int __init use_1to1_mapping(struct device_node *pp) +{ + char *model; + + /* If this is on the PMU bus, don't try to translate it even + * if a ranges property exists. + */ + if (!strcmp(pp->name, "pmu")) return 1; - memcpy(addr, ranges + na, 4 * pna); + /* If we have a ranges property in the parent, use it. */ + if (of_find_property(pp, "ranges", NULL) != NULL) + return 0; -finish: - /* Translate it into parent bus space */ - return pbus->translate(addr, offset, pna); + /* If the parent is the dma node of an ISA bus, pass + * the translation up to the root. + */ + if (!strcmp(pp->name, "dma")) + return 0; + + /* Similarly for Simba PCI bridges. */ + model = of_get_property(pp, "model", NULL); + if (model && !strcmp(model, "SUNW,simba")) + return 0; + + return 1; } +static int of_resource_verbose; + static void __init build_device_resources(struct of_device *op, struct device *parent) { @@ -564,15 +562,7 @@ static void __init build_device_resources(struct of_device *op, memcpy(addr, reg, na * 4); - /* If the immediate parent has no ranges property to apply, - * just use a 1<->1 mapping. Unless it is the 'dma' child - * of an isa bus, which must be passed up towards the root. - * - * Also, don't try to translate PMU bus device registers. - */ - if ((of_find_property(pp, "ranges", NULL) == NULL && - strcmp(pp->name, "dma") != 0) || - !strcmp(pp->name, "pmu")) { + if (use_1to1_mapping(pp)) { result = of_read_addr(addr, na); goto build_res; } @@ -591,7 +581,8 @@ static void __init build_device_resources(struct of_device *op, pbus = of_match_bus(pp); pbus->count_cells(dp, &pna, &pns); - if (build_one_resource(dp, bus, pbus, addr, dna, dns, pna)) + if (build_one_resource(dp, bus, pbus, addr, + dna, dns, pna)) break; dna = pna; @@ -601,6 +592,12 @@ static void __init build_device_resources(struct of_device *op, build_res: memset(r, 0, sizeof(*r)); + + if (of_resource_verbose) + printk("%s reg[%d] -> %lx\n", + op->node->full_name, index, + result); + if (result != OF_BAD_ADDR) { if (tlb_type == hypervisor) result &= 0x0fffffffffffffffUL; @@ -684,6 +681,8 @@ static unsigned int __init pci_irq_swizzle(struct device_node *dp, return ret; } +static int of_irq_verbose; + static unsigned int __init build_one_device_irq(struct of_device *op, struct device *parent, unsigned int irq) @@ -698,10 +697,11 @@ static unsigned int __init build_one_device_irq(struct of_device *op, if (dp->irq_trans) { irq = dp->irq_trans->irq_build(dp, irq, dp->irq_trans->data); -#if 1 - printk("%s: direct translate %x --> %x\n", - dp->full_name, orig_irq, irq); -#endif + + if (of_irq_verbose) + printk("%s: direct translate %x --> %x\n", + dp->full_name, orig_irq, irq); + return irq; } @@ -728,12 +728,13 @@ static unsigned int __init build_one_device_irq(struct of_device *op, iret = apply_interrupt_map(dp, pp, imap, imlen, imsk, &irq); -#if 1 - printk("%s: Apply [%s:%x] imap --> [%s:%x]\n", - op->node->full_name, - pp->full_name, this_orig_irq, - (iret ? iret->full_name : "NULL"), irq); -#endif + + if (of_irq_verbose) + printk("%s: Apply [%s:%x] imap --> [%s:%x]\n", + op->node->full_name, + pp->full_name, this_orig_irq, + (iret ? iret->full_name : "NULL"), irq); + if (!iret) break; @@ -747,11 +748,13 @@ static unsigned int __init build_one_device_irq(struct of_device *op, unsigned int this_orig_irq = irq; irq = pci_irq_swizzle(dp, pp, irq); -#if 1 - printk("%s: PCI swizzle [%s] %x --> %x\n", - op->node->full_name, - pp->full_name, this_orig_irq, irq); -#endif + if (of_irq_verbose) + printk("%s: PCI swizzle [%s] " + "%x --> %x\n", + op->node->full_name, + pp->full_name, this_orig_irq, + irq); + } if (pp->irq_trans) { @@ -767,10 +770,9 @@ static unsigned int __init build_one_device_irq(struct of_device *op, irq = ip->irq_trans->irq_build(op->node, irq, ip->irq_trans->data); -#if 1 - printk("%s: Apply IRQ trans [%s] %x --> %x\n", - op->node->full_name, ip->full_name, orig_irq, irq); -#endif + if (of_irq_verbose) + printk("%s: Apply IRQ trans [%s] %x --> %x\n", + op->node->full_name, ip->full_name, orig_irq, irq); return irq; } @@ -870,6 +872,20 @@ static int __init of_bus_driver_init(void) postcore_initcall(of_bus_driver_init); +static int __init of_debug(char *str) +{ + int val = 0; + + get_option(&str, &val); + if (val & 1) + of_resource_verbose = 1; + if (val & 2) + of_irq_verbose = 1; + return 1; +} + +__setup("of_debug=", of_debug); + int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) { /* initialize common driver fields */ -- cgit v1.2.3-70-g09d2 From 06ffd7956e4790d824b4b5575b56def8448ec6d4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 16 Jul 2006 22:19:40 -0700 Subject: [SPARC]: Kill prom_getname, unused and not implemented properly. The m68k port's sun3 asm/oplib.h had a stray reference too, so I killed that off as well. Signed-off-by: David S. Miller --- arch/sparc/kernel/sparc_ksyms.c | 1 - arch/sparc/prom/tree.c | 18 -------- arch/sparc64/kernel/sparc64_ksyms.c | 1 - arch/sparc64/prom/tree.c | 85 ------------------------------------- include/asm-m68k/oplib.h | 5 --- include/asm-sparc/oplib.h | 5 --- include/asm-sparc64/oplib.h | 5 --- 7 files changed, 120 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 5fb987fc3d6..4d441a554d3 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); EXPORT_SYMBOL(prom_setprop); EXPORT_SYMBOL(saved_command_line); EXPORT_SYMBOL(prom_apply_obio_ranges); -EXPORT_SYMBOL(prom_getname); EXPORT_SYMBOL(prom_feval); EXPORT_SYMBOL(prom_getbool); EXPORT_SYMBOL(prom_getstring); diff --git a/arch/sparc/prom/tree.c b/arch/sparc/prom/tree.c index 2bf03ee8cde..5ec246573a9 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) return 0; } -/* Gets name in the form prom v2+ uses it (name@x,yyyyy or name (if no reg)) */ -int prom_getname (int node, char *buffer, int len) -{ - int i; - struct linux_prom_registers reg[PROMREG_MAX]; - - i = prom_getproperty (node, "name", buffer, len); - if (i <= 0) return -1; - buffer [i] = 0; - len -= i; - i = prom_getproperty (node, "reg", (char *)reg, sizeof (reg)); - if (i <= 0) return 0; - if (len < 11) return -1; - buffer = strchr (buffer, 0); - sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr); - return 0; -} - /* Interal version of nextprop that does not alter return values. */ char * __prom_nextprop(int node, char * oprop) { diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 237524d87ca..beffc82a1e8 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -254,7 +254,6 @@ EXPORT_SYMBOL(prom_getproperty); EXPORT_SYMBOL(prom_node_has_property); EXPORT_SYMBOL(prom_setprop); EXPORT_SYMBOL(saved_command_line); -EXPORT_SYMBOL(prom_getname); EXPORT_SYMBOL(prom_finddevice); EXPORT_SYMBOL(prom_feval); EXPORT_SYMBOL(prom_getbool); diff --git a/arch/sparc64/prom/tree.c b/arch/sparc64/prom/tree.c index 49075abd7cb..500f05e2cfc 100644 --- a/arch/sparc64/prom/tree.c +++ b/arch/sparc64/prom/tree.c @@ -193,91 +193,6 @@ prom_searchsiblings(int node_start, const char *nodename) return 0; } -/* Gets name in the {name@x,yyyyy|name (if no reg)} form */ -int -prom_getname (int node, char *buffer, int len) -{ - int i, sbus = 0; - int pci = 0, ebus = 0, ide = 0; - struct linux_prom_registers *reg; - struct linux_prom64_registers reg64[PROMREG_MAX]; - - for (sbus = prom_getparent (node); sbus; sbus = prom_getparent (sbus)) { - i = prom_getproperty (sbus, "name", buffer, len); - if (i > 0) { - buffer [i] = 0; - if (!strcmp (buffer, "sbus")) - goto getit; - } - } - if ((pci = prom_getparent (node))) { - i = prom_getproperty (pci, "name", buffer, len); - if (i > 0) { - buffer [i] = 0; - if (!strcmp (buffer, "pci")) - goto getit; - } - pci = 0; - } - if ((ebus = prom_getparent (node))) { - i = prom_getproperty (ebus, "name", buffer, len); - if (i > 0) { - buffer[i] = 0; - if (!strcmp (buffer, "ebus")) - goto getit; - } - ebus = 0; - } - if ((ide = prom_getparent (node))) { - i = prom_getproperty (ide, "name", buffer, len); - if (i > 0) { - buffer [i] = 0; - if (!strcmp (buffer, "ide")) - goto getit; - } - ide = 0; - } -getit: - i = prom_getproperty (node, "name", buffer, len); - if (i <= 0) { - buffer [0] = 0; - return -1; - } - buffer [i] = 0; - len -= i; - i = prom_getproperty (node, "reg", (char *)reg64, sizeof (reg64)); - if (i <= 0) return 0; - if (len < 16) return -1; - buffer = strchr (buffer, 0); - if (sbus) { - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x,%x", reg[0].which_io, (uint)reg[0].phys_addr); - } else if (pci) { - int dev, fn; - reg = (struct linux_prom_registers *)reg64; - fn = (reg[0].which_io >> 8) & 0x07; - dev = (reg[0].which_io >> 11) & 0x1f; - if (fn) - sprintf (buffer, "@%x,%x", dev, fn); - else - sprintf (buffer, "@%x", dev); - } else if (ebus) { - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr); - } else if (ide) { - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x,%x", reg[0].which_io, reg[0].phys_addr); - } else if (i == 4) { /* Happens on 8042's children on Ultra/PCI. */ - reg = (struct linux_prom_registers *)reg64; - sprintf (buffer, "@%x", reg[0].which_io); - } else { - sprintf (buffer, "@%x,%x", - (unsigned int)(reg64[0].phys_addr >> 36), - (unsigned int)(reg64[0].phys_addr)); - } - return 0; -} - /* Return the first property type for node 'node'. * buffer should be at least 32B in length */ diff --git a/include/asm-m68k/oplib.h b/include/asm-m68k/oplib.h index c3594f473ef..06caa2d0845 100644 --- a/include/asm-m68k/oplib.h +++ b/include/asm-m68k/oplib.h @@ -244,11 +244,6 @@ extern void prom_getstring(int node, char *prop, char *buf, int bufsize); /* Does the passed node have the given "name"? YES=1 NO=0 */ extern int prom_nodematch(int thisnode, char *name); -/* Puts in buffer a prom name in the form name@x,y or name (x for which_io - * and y for first regs phys address - */ -extern int prom_getname(int node, char *buf, int buflen); - /* Search all siblings starting at the passed node for "name" matching * the given string. Returns the node on success, zero on failure. */ diff --git a/include/asm-sparc/oplib.h b/include/asm-sparc/oplib.h index f283f8aaf6a..91691e52c05 100644 --- a/include/asm-sparc/oplib.h +++ b/include/asm-sparc/oplib.h @@ -267,11 +267,6 @@ extern void prom_getstring(int node, char *prop, char *buf, int bufsize); /* Does the passed node have the given "name"? YES=1 NO=0 */ extern int prom_nodematch(int thisnode, char *name); -/* Puts in buffer a prom name in the form name@x,y or name (x for which_io - * and y for first regs phys address - */ -extern int prom_getname(int node, char *buf, int buflen); - /* Search all siblings starting at the passed node for "name" matching * the given string. Returns the node on success, zero on failure. */ diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h index a68b0bb0595..6a0da3b1695 100644 --- a/include/asm-sparc64/oplib.h +++ b/include/asm-sparc64/oplib.h @@ -287,11 +287,6 @@ extern void prom_getstring(int node, const char *prop, char *buf, int bufsize); /* Does the passed node have the given "name"? YES=1 NO=0 */ extern int prom_nodematch(int thisnode, const char *name); -/* Puts in buffer a prom name in the form name@x,y or name (x for which_io - * and y for first regs phys address - */ -extern int prom_getname(int node, char *buf, int buflen); - /* Search all siblings starting at the passed node for "name" matching * the given string. Returns the node on success, zero on failure. */ -- cgit v1.2.3-70-g09d2 From f7785a64d117951e4c2bf9418d8c1dd59fe53b36 Mon Sep 17 00:00:00 2001 From: Bob Breuer Date: Mon, 17 Jul 2006 17:05:56 -0700 Subject: [SPARC]: Fix property name acquisition in prom.c On sparc32 the prom_{first,next}prop() interfaces work a little differently. The buffer argument is ignored on sparc32 and the firmware just returns a raw pointer to the property name. Signed-off-by: David S. Miller --- arch/sparc/kernel/prom.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 4b06dcb00eb..4ca9e5fc97f 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 static struct property *tmp = NULL; struct property *p; int len; + const char *name; if (tmp) { p = tmp; @@ -456,19 +457,21 @@ static struct property * __init build_one_prop(phandle node, char *prev, char *s p->name = (char *) (p + 1); if (special_name) { + strcpy(p->name, special_name); p->length = special_len; p->value = prom_early_alloc(special_len); memcpy(p->value, special_val, special_len); } else { if (prev == NULL) { - prom_firstprop(node, p->name); + name = prom_firstprop(node, NULL); } else { - prom_nextprop(node, prev, p->name); + name = prom_nextprop(node, prev, NULL); } - if (strlen(p->name) == 0) { + if (strlen(name) == 0) { tmp = p; return NULL; } + strcpy(p->name, name); p->length = prom_getproplen(node, p->name); if (p->length <= 0) { p->length = 0; -- cgit v1.2.3-70-g09d2 From 9d7ab1f4d56dffcddc1177b3cd55b6da6620e1e1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 17 Jul 2006 21:39:09 -0700 Subject: [SPARC]: Fix initialization of sun4d SBUS interrupts. 1) Explicitly traverse to the root looking for the "sbi". 2) Grab the "board#" property from the sbi's parent and verify that this parent is an "io-unit" node. 3) Skip IRQ initialization when device lacks "reg" property. Signed-off-by: David S. Miller --- arch/sparc/kernel/of_device.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 5a2faad5d04..97bf87e8cdd 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -596,14 +596,41 @@ static struct of_device * __init scan_one_device(struct device_node *dp, static int pil_to_sbus[] = { 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, }; - struct device_node *busp = dp->parent; + struct device_node *io_unit, *sbi = dp->parent; struct linux_prom_registers *regs; - int board = of_getintprop_default(busp, "board#", 0); - int slot; + int board, slot; + + while (sbi) { + if (!strcmp(sbi->name, "sbi")) + break; + + sbi = sbi->parent; + } + if (!sbi) + goto build_resources; regs = of_get_property(dp, "reg", NULL); + if (!regs) + goto build_resources; + slot = regs->which_io; + /* If SBI's parent is not io-unit or the io-unit lacks + * a "board#" property, something is very wrong. + */ + if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { + printk("%s: Error, parent is not io-unit.\n", + sbi->full_name); + goto build_resources; + } + io_unit = sbi->parent; + board = of_getintprop_default(io_unit, "board#", -1); + if (board == -1) { + printk("%s: Error, lacks board# property.\n", + io_unit->full_name); + goto build_resources; + } + for (i = 0; i < op->num_irqs; i++) { int this_irq = op->irqs[i]; int sbusl = pil_to_sbus[this_irq]; @@ -617,6 +644,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, } } +build_resources: build_device_resources(op, parent); op->dev.parent = parent; -- cgit v1.2.3-70-g09d2 From c2d3bffebc2cb651ed33abae2434f85cd503a498 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 17 Jul 2006 21:49:58 -0700 Subject: [SPARC]: Simplify and correct __cpu_find_by() By using for_each_node_by_type(). Also, correct a spurioud test in check_cpu_node() on sparc64. It is only called with nodes that have device_type "cpu". Signed-off-by: David S. Miller --- arch/sparc/kernel/devices.c | 25 +++++++------------------ arch/sparc64/kernel/devices.c | 3 --- 2 files changed, 7 insertions(+), 21 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index adba9dfee35..af90a5f9ab5 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -34,12 +35,6 @@ static int check_cpu_node(int nd, int *cur_inst, int (*compare)(int, int, void *), void *compare_arg, int *prom_node, int *mid) { - char node_str[128]; - - prom_getstring(nd, "device_type", node_str, sizeof(node_str)); - if (strcmp(node_str, "cpu")) - return -ENODEV; - if (!compare(nd, *cur_inst, compare_arg)) { if (prom_node) *prom_node = nd; @@ -59,20 +54,14 @@ static int check_cpu_node(int nd, int *cur_inst, static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg, int *prom_node, int *mid) { - int nd, cur_inst, err; + struct device_node *dp; + int cur_inst; - nd = prom_root_node; cur_inst = 0; - - err = check_cpu_node(nd, &cur_inst, compare, compare_arg, - prom_node, mid); - if (!err) - return 0; - - nd = prom_getchild(nd); - while ((nd = prom_getsibling(nd)) != 0) { - err = check_cpu_node(nd, &cur_inst, compare, compare_arg, - prom_node, mid); + for_each_node_by_type(dp, "cpu") { + int err = check_cpu_node(dp->node, &cur_inst, + compare, compare_arg, + prom_node, mid); if (!err) return 0; } diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c index f8ef2f2b9b3..ec10f7edcf8 100644 --- a/arch/sparc64/kernel/devices.c +++ b/arch/sparc64/kernel/devices.c @@ -66,9 +66,6 @@ static int check_cpu_node(struct device_node *dp, int *cur_inst, void *compare_arg, struct device_node **dev_node, int *mid) { - if (strcmp(dp->type, "cpu")) - return -ENODEV; - if (!compare(dp, *cur_inst, compare_arg)) { if (dev_node) *dev_node = dp; -- cgit v1.2.3-70-g09d2 From 198c167c5424d30d4f6687aed6e54ef71036f8e9 Mon Sep 17 00:00:00 2001 From: Raymond Burns Date: Mon, 17 Jul 2006 21:50:55 -0700 Subject: [SPARC]: Do not call sun4m_irq_rotate on sun4d. Signed-off-by: David S. Miller --- arch/sparc/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index cde73327ca9..72f0201051a 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) disable_pil_irq(irq); #ifdef CONFIG_SMP /* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */ - if(irq < 10) + if((sparc_cpu_model==sun4m) && (irq < 10)) smp4m_irq_rotate(cpu); #endif action = sparc_irq[irq].action; -- cgit v1.2.3-70-g09d2 From 8b3c848cc89e62904e6d9c8f9fed13d5c225572d Mon Sep 17 00:00:00 2001 From: Raymond Burns Date: Mon, 17 Jul 2006 21:57:09 -0700 Subject: [SPARC]: Get sun4d SMP building again. Signed-off-by: David S. Miller --- arch/sparc/kernel/smp.c | 96 ++++++++++++++++++++++++++++++++++++--- arch/sparc/kernel/sun4d_smp.c | 103 +++++++++++++----------------------------- 2 files changed, 121 insertions(+), 78 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 6135d4faeee..e311ade1b49 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -87,6 +87,7 @@ void __cpuinit smp_store_cpu_info(int id) void __init smp_cpus_done(unsigned int max_cpus) { extern void smp4m_smp_done(void); + extern void smp4d_smp_done(void); unsigned long bogosum = 0; int cpu, num; @@ -100,8 +101,34 @@ void __init smp_cpus_done(unsigned int max_cpus) num, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); - BUG_ON(sparc_cpu_model != sun4m); - smp4m_smp_done(); + switch(sparc_cpu_model) { + case sun4: + printk("SUN4\n"); + BUG(); + break; + case sun4c: + printk("SUN4C\n"); + BUG(); + break; + case sun4m: + smp4m_smp_done(); + break; + case sun4d: + smp4d_smp_done(); + break; + case sun4e: + printk("SUN4E\n"); + BUG(); + break; + case sun4u: + printk("SUN4U\n"); + BUG(); + break; + default: + printk("UNKNOWN!\n"); + BUG(); + break; + }; } void cpu_panic(void) @@ -267,9 +294,9 @@ int setup_profiling_timer(unsigned int multiplier) void __init smp_prepare_cpus(unsigned int max_cpus) { extern void smp4m_boot_cpus(void); + extern void smp4d_boot_cpus(void); int i, cpuid, extra; - BUG_ON(sparc_cpu_model != sun4m); printk("Entering SMP Mode...\n"); extra = 0; @@ -283,7 +310,34 @@ void __init smp_prepare_cpus(unsigned int max_cpus) smp_store_cpu_info(boot_cpu_id); - smp4m_boot_cpus(); + switch(sparc_cpu_model) { + case sun4: + printk("SUN4\n"); + BUG(); + break; + case sun4c: + printk("SUN4C\n"); + BUG(); + break; + case sun4m: + smp4m_boot_cpus(); + break; + case sun4d: + smp4d_boot_cpus(); + break; + case sun4e: + printk("SUN4E\n"); + BUG(); + break; + case sun4u: + printk("SUN4U\n"); + BUG(); + break; + default: + printk("UNKNOWN!\n"); + BUG(); + break; + }; } /* Set this up early so that things like the scheduler can init @@ -323,9 +377,37 @@ void __init smp_prepare_boot_cpu(void) int __cpuinit __cpu_up(unsigned int cpu) { extern int smp4m_boot_one_cpu(int); - int ret; - - ret = smp4m_boot_one_cpu(cpu); + extern int smp4d_boot_one_cpu(int); + int ret=0; + + switch(sparc_cpu_model) { + case sun4: + printk("SUN4\n"); + BUG(); + break; + case sun4c: + printk("SUN4C\n"); + BUG(); + break; + case sun4m: + ret = smp4m_boot_one_cpu(cpu); + break; + case sun4d: + ret = smp4d_boot_one_cpu(cpu); + break; + case sun4e: + printk("SUN4E\n"); + BUG(); + break; + case sun4u: + printk("SUN4U\n"); + BUG(); + break; + default: + printk("UNKNOWN!\n"); + BUG(); + break; + }; if (!ret) { cpu_set(cpu, smp_commenced_mask); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index b141b7ee671..ba843f6a283 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -43,15 +43,10 @@ extern ctxd_t *srmmu_ctx_table_phys; extern void calibrate_delay(void); extern volatile int smp_processors_ready; -extern int smp_num_cpus; static int smp_highest_cpu; extern volatile unsigned long cpu_callin_map[NR_CPUS]; extern cpuinfo_sparc cpu_data[NR_CPUS]; extern unsigned char boot_cpu_id; -extern int smp_activated; -extern volatile int __cpu_number_map[NR_CPUS]; -extern volatile int __cpu_logical_map[NR_CPUS]; -extern volatile unsigned long ipi_count; extern volatile int smp_process_available; extern cpumask_t smp_commenced_mask; @@ -144,6 +139,8 @@ void __init smp4d_callin(void) spin_lock_irqsave(&sun4d_imsk_lock, flags); cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */ spin_unlock_irqrestore(&sun4d_imsk_lock, flags); + cpu_set(cpuid, cpu_online_map); + } extern void init_IRQ(void); @@ -160,51 +157,24 @@ extern unsigned long trapbase_cpu3[]; void __init smp4d_boot_cpus(void) { - int cpucount = 0; - int i, mid; - - printk("Entering SMP Mode...\n"); - if (boot_cpu_id) current_set[0] = NULL; - - local_irq_enable(); - cpus_clear(cpu_present_map); - - /* XXX This whole thing has to go. See sparc64. */ - for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) - cpu_set(mid, cpu_present_map); - SMP_PRINTK(("cpu_present_map %08lx\n", cpus_addr(cpu_present_map)[0])); - for(i=0; i < NR_CPUS; i++) - __cpu_number_map[i] = -1; - for(i=0; i < NR_CPUS; i++) - __cpu_logical_map[i] = -1; - __cpu_number_map[boot_cpu_id] = 0; - __cpu_logical_map[0] = boot_cpu_id; - current_thread_info()->cpu = boot_cpu_id; - smp_store_cpu_info(boot_cpu_id); smp_setup_percpu_timer(); local_flush_cache_all(); - if (cpu_find_by_instance(1, NULL, NULL)) - return; /* Not an MP box. */ - SMP_PRINTK(("Iterating over CPUs\n")); - for(i = 0; i < NR_CPUS; i++) { - if(i == boot_cpu_id) - continue; - - if (cpu_isset(i, cpu_present_map)) { +} + +int smp4d_boot_one_cpu(int i) +{ extern unsigned long sun4d_cpu_startup; unsigned long *entry = &sun4d_cpu_startup; struct task_struct *p; int timeout; - int no; + int cpu_node; + cpu_find_by_instance(i, &cpu_node,NULL); /* Cook up an idler for this guy. */ p = fork_idle(i); - cpucount++; current_set[i] = task_thread_info(p); - for (no = 0; !cpu_find_by_instance(no, NULL, &mid) - && mid != i; no++) ; /* * Initialize the contexts table @@ -216,9 +186,9 @@ void __init smp4d_boot_cpus(void) smp_penguin_ctable.reg_size = 0; /* whirrr, whirrr, whirrrrrrrrr... */ - SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, cpu_data(no).prom_node)); + SMP_PRINTK(("Starting CPU %d at %p \n", i, entry)); local_flush_cache_all(); - prom_startcpu(cpu_data(no).prom_node, + prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry); SMP_PRINTK(("prom_startcpu returned :)\n")); @@ -230,39 +200,30 @@ void __init smp4d_boot_cpus(void) udelay(200); } - if(cpu_callin_map[i]) { - /* Another "Red Snapper". */ - __cpu_number_map[i] = cpucount; - __cpu_logical_map[cpucount] = i; - } else { - cpucount--; - printk("Processor %d is stuck.\n", i); - } - } - if(!(cpu_callin_map[i])) { - cpu_clear(i, cpu_present_map); - __cpu_number_map[i] = -1; - } + if (!(cpu_callin_map[i])) { + printk("Processor %d is stuck.\n", i); + return -ENODEV; + } local_flush_cache_all(); - if(cpucount == 0) { - printk("Error: only one Processor found.\n"); - cpu_present_map = cpumask_of_cpu(hard_smp4d_processor_id()); - } else { - unsigned long bogosum = 0; - - for_each_present_cpu(i) { - bogosum += cpu_data(i).udelay_val; - smp_highest_cpu = i; + return 0; +} + +void __init smp4d_smp_done(void) +{ + int i, first; + int *prev; + + /* setup cpu list for irq rotation */ + first = 0; + prev = &first; + for (i = 0; i < NR_CPUS; i++) + if (cpu_online(i)) { + *prev = i; + prev = &cpu_data(i).next; } - SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100)); - printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", - cpucount + 1, - bogosum/(500000/HZ), - (bogosum/(5000/HZ))%100); - smp_activated = 1; - smp_num_cpus = cpucount + 1; - } + *prev = first; + local_flush_cache_all(); /* Free unneeded trap tables */ ClearPageReserved(virt_to_page(trapbase_cpu1)); @@ -334,7 +295,7 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2, register int i; mask = cpumask_of_cpu(hard_smp4d_processor_id()); - cpus_andnot(mask, cpu_present_map, mask); + cpus_andnot(mask, cpu_online_map, mask); for(i = 0; i <= high; i++) { if (cpu_isset(i, mask)) { ccall_info.processors_in[i] = 0; -- cgit v1.2.3-70-g09d2 From 8310a32c15c76623bbe2425d38688a9d5b3e50a9 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 21 Jul 2006 14:12:39 -0700 Subject: [SPARC]: Fix length parameter verification in sys_getdomainname(). Found by scrashme. Signed-off-by: David S. Miller --- arch/sparc/kernel/sys_sparc.c | 18 +++++++++--------- arch/sparc64/kernel/sys_sparc.c | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 0cdfc9d294b..a41c8a5c200 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -465,21 +465,21 @@ sys_rt_sigaction(int sig, asmlinkage int sys_getdomainname(char __user *name, int len) { - int nlen; - int err = -EFAULT; + int nlen, err; + if (len < 0 || len > __NEW_UTS_LEN) + return -EINVAL; + down_read(&uts_sem); nlen = strlen(system_utsname.domainname) + 1; - if (nlen < len) len = nlen; - if (len > __NEW_UTS_LEN) - goto done; - if (copy_to_user(name, system_utsname.domainname, len)) - goto done; - err = 0; -done: + + err = -EFAULT; + if (!copy_to_user(name, system_utsname.domainname, len)) + err = 0; + up_read(&uts_sem); return err; } diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 51c056df528..054d0abdb7e 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -701,21 +701,21 @@ extern void check_pending(int signum); asmlinkage long sys_getdomainname(char __user *name, int len) { - int nlen; - int err = -EFAULT; + int nlen, err; + + if (len < 0 || len > __NEW_UTS_LEN) + return -EINVAL; down_read(&uts_sem); nlen = strlen(system_utsname.domainname) + 1; - if (nlen < len) len = nlen; - if (len > __NEW_UTS_LEN) - goto done; - if (copy_to_user(name, system_utsname.domainname, len)) - goto done; - err = 0; -done: + + err = -EFAULT; + if (!copy_to_user(name, system_utsname.domainname, len)) + err = 0; + up_read(&uts_sem); return err; } -- cgit v1.2.3-70-g09d2 From 96ba989d22de779ca19ca214e2b2e53a4ca86b7b Mon Sep 17 00:00:00 2001 From: Bob Breuer Date: Thu, 27 Jul 2006 22:08:01 -0700 Subject: [SPARC]: Defer clock_probe to fs_initcall() From: Bob Breuer That way all the of_driver bits will be ready. Signed-off-by: David S. Miller --- arch/sparc/kernel/time.c | 74 +++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 32 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 04eb1eab6e3..845081b0126 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -225,6 +225,32 @@ static __inline__ int has_low_battery(void) return (data1 == data2); /* Was the write blocked? */ } +static void __init mostek_set_system_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + struct mostek48t02 *mregs; + + mregs = (struct mostek48t02 *)mstk48t02_regs; + if(!mregs) { + prom_printf("Something wrong, clock regs not mapped yet.\n"); + prom_halt(); + } + spin_lock_irq(&mostek_lock); + mregs->creg |= MSTK_CREG_READ; + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); + mregs->creg &= ~MSTK_CREG_READ; + spin_unlock_irq(&mostek_lock); +} + /* Probe for the real time clock chip on Sun4 */ static __inline__ void sun4_clock_probe(void) { @@ -273,6 +299,7 @@ static __inline__ void sun4_clock_probe(void) #endif } +#ifndef CONFIG_SUN4 static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; @@ -307,6 +334,8 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) kick_start_clock(); + mostek_set_system_time(); + return 0; } @@ -325,56 +354,37 @@ static struct of_platform_driver clock_driver = { /* Probe for the mostek real time clock chip. */ -static void clock_init(void) +static int __init clock_init(void) { - of_register_driver(&clock_driver, &of_bus_type); + return of_register_driver(&clock_driver, &of_bus_type); } +/* Must be after subsys_initcall() so that busses are probed. Must + * be before device_initcall() because things like the RTC driver + * need to see the clock registers. + */ +fs_initcall(clock_init); +#endif /* !CONFIG_SUN4 */ + void __init sbus_time_init(void) { - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - -#ifdef CONFIG_SUN4 - int temp; - struct intersil *iregs; -#endif BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); if (ARCH_SUN4) sun4_clock_probe(); - else - clock_init(); sparc_init_timers(timer_interrupt); #ifdef CONFIG_SUN4 if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { -#endif - mregs = (struct mostek48t02 *)mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - spin_lock_irq(&mostek_lock); - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - mregs->creg &= ~MSTK_CREG_READ; - spin_unlock_irq(&mostek_lock); -#ifdef CONFIG_SUN4 + mostek_set_system_time(); } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { /* initialise the intersil on sun4 */ + unsigned int year, mon, day, hour, min, sec; + int temp; + struct intersil *iregs; iregs=intersil_clock; if(!iregs) { -- cgit v1.2.3-70-g09d2