diff --git a/[refs] b/[refs] index 99e28983e11e..79d18da81371 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d02f40e81e003be6ddba5c176f2e40ea290c3729 +refs/heads/master: 8fae097debdf8ac9b66d220ac258535ea09f3898 diff --git a/trunk/arch/i386/kernel/vmlinux.lds.S b/trunk/arch/i386/kernel/vmlinux.lds.S index 7512f39c9f25..8831303a473f 100644 --- a/trunk/arch/i386/kernel/vmlinux.lds.S +++ b/trunk/arch/i386/kernel/vmlinux.lds.S @@ -37,13 +37,6 @@ SECTIONS RODATA - . = ALIGN(4); - __tracedata_start = .; - .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { - *(.tracedata) - } - __tracedata_end = .; - /* writeable */ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ *(.data) diff --git a/trunk/arch/sparc/kernel/ioport.c b/trunk/arch/sparc/kernel/ioport.c index f9ff29734848..00cf41182912 100644 --- a/trunk/arch/sparc/kernel/ioport.c +++ b/trunk/arch/sparc/kernel/ioport.c @@ -224,10 +224,54 @@ static void _sparc_free_io(struct resource *res) #ifdef CONFIG_SBUS -void sbus_set_sbus64(struct sbus_dev *sdev, int x) { +void sbus_set_sbus64(struct sbus_dev *sdev, int x) +{ printk("sbus_set_sbus64: unsupported\n"); } +extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); +void __init sbus_fill_device_irq(struct sbus_dev *sdev) +{ + struct linux_prom_irqs irqs[PROMINTR_MAX]; + int len; + + len = prom_getproperty(sdev->prom_node, "intr", + (char *)irqs, sizeof(irqs)); + if (len != -1) { + sdev->num_irqs = len / 8; + if (sdev->num_irqs == 0) { + sdev->irqs[0] = 0; + } else if (sparc_cpu_model == sun4d) { + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = + sun4d_build_irq(sdev, irqs[len].pri); + } else { + for (len = 0; len < sdev->num_irqs; len++) + sdev->irqs[len] = irqs[len].pri; + } + } else { + int interrupts[PROMINTR_MAX]; + + /* No "intr" node found-- check for "interrupts" node. + * This node contains SBus interrupt levels, not IPLs + * as in "intr", and no vector values. We convert + * SBus interrupt levels to PILs (platform specific). + */ + len = prom_getproperty(sdev->prom_node, "interrupts", + (char *)interrupts, sizeof(interrupts)); + if (len == -1) { + sdev->irqs[0] = 0; + sdev->num_irqs = 0; + } else { + sdev->num_irqs = len / sizeof(int); + for (len = 0; len < sdev->num_irqs; len++) { + sdev->irqs[len] = + sbint_to_irq(sdev, interrupts[len]); + } + } + } +} + /* * Allocate a chunk of memory suitable for DMA. * Typically devices use them for control blocks. diff --git a/trunk/arch/sparc64/kernel/sbus.c b/trunk/arch/sparc64/kernel/sbus.c index 8812417247d4..8f7877ac858f 100644 --- a/trunk/arch/sparc64/kernel/sbus.c +++ b/trunk/arch/sparc64/kernel/sbus.c @@ -1225,3 +1225,24 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus) sysio_register_error_handlers(sbus); } + +void sbus_fill_device_irq(struct sbus_dev *sdev) +{ + struct linux_prom_irqs irqs[PROMINTR_MAX]; + int len; + + len = prom_getproperty(sdev->prom_node, "interrupts", + (char *) irqs, sizeof(irqs)); + if (len == -1 || len == 0) { + sdev->irqs[0] = 0; + sdev->num_irqs = 0; + } else { + unsigned int pri = irqs[0].pri; + + sdev->num_irqs = 1; + if (pri < 0x20) + pri += sdev->slot * 8; + + sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); + } +} diff --git a/trunk/drivers/base/power/Makefile b/trunk/drivers/base/power/Makefile index 91f230939c1e..ceeeba2c56c7 100644 --- a/trunk/drivers/base/power/Makefile +++ b/trunk/drivers/base/power/Makefile @@ -1,6 +1,5 @@ obj-y := shutdown.o obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o -obj-$(CONFIG_PM_TRACE) += trace.o ifeq ($(CONFIG_DEBUG_DRIVER),y) EXTRA_CFLAGS += -DDEBUG diff --git a/trunk/drivers/base/power/resume.c b/trunk/drivers/base/power/resume.c index 520679ce53a8..317edbf0feca 100644 --- a/trunk/drivers/base/power/resume.c +++ b/trunk/drivers/base/power/resume.c @@ -9,7 +9,6 @@ */ #include -#include #include "../base.h" #include "power.h" @@ -24,8 +23,6 @@ int resume_device(struct device * dev) { int error = 0; - TRACE_DEVICE(dev); - TRACE_RESUME(0); down(&dev->sem); if (dev->power.pm_parent && dev->power.pm_parent->power.power_state.event) { @@ -39,7 +36,6 @@ int resume_device(struct device * dev) error = dev->bus->resume(dev); } up(&dev->sem); - TRACE_RESUME(error); return error; } diff --git a/trunk/drivers/base/power/trace.c b/trunk/drivers/base/power/trace.c deleted file mode 100644 index a9ab30fefffc..000000000000 --- a/trunk/drivers/base/power/trace.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * drivers/base/power/trace.c - * - * Copyright (C) 2006 Linus Torvalds - * - * Trace facility for suspend/resume problems, when none of the - * devices may be working. - */ - -#include -#include - -#include - -#include "power.h" - -/* - * Horrid, horrid, horrid. - * - * It turns out that the _only_ piece of hardware that actually - * keeps its value across a hard boot (and, more importantly, the - * POST init sequence) is literally the realtime clock. - * - * Never mind that an RTC chip has 114 bytes (and often a whole - * other bank of an additional 128 bytes) of nice SRAM that is - * _designed_ to keep data - the POST will clear it. So we literally - * can just use the few bytes of actual time data, which means that - * we're really limited. - * - * It means, for example, that we can't use the seconds at all - * (since the time between the hang and the boot might be more - * than a minute), and we'd better not depend on the low bits of - * the minutes either. - * - * There are the wday fields etc, but I wouldn't guarantee those - * are dependable either. And if the date isn't valid, either the - * hw or POST will do strange things. - * - * So we're left with: - * - year: 0-99 - * - month: 0-11 - * - day-of-month: 1-28 - * - hour: 0-23 - * - min: (0-30)*2 - * - * Giving us a total range of 0-16128000 (0xf61800), ie less - * than 24 bits of actual data we can save across reboots. - * - * And if your box can't boot in less than three minutes, - * you're screwed. - * - * Now, almost 24 bits of data is pitifully small, so we need - * to be pretty dense if we want to use it for anything nice. - * What we do is that instead of saving off nice readable info, - * we save off _hashes_ of information that we can hopefully - * regenerate after the reboot. - * - * In particular, this means that we might be unlucky, and hit - * a case where we have a hash collision, and we end up not - * being able to tell for certain exactly which case happened. - * But that's hopefully unlikely. - * - * What we do is to take the bits we can fit, and split them - * into three parts (16*997*1009 = 16095568), and use the values - * for: - * - 0-15: user-settable - * - 0-996: file + line number - * - 0-1008: device - */ -#define USERHASH (16) -#define FILEHASH (997) -#define DEVHASH (1009) - -#define DEVSEED (7919) - -static unsigned int dev_hash_value; - -static int set_magic_time(unsigned int user, unsigned int file, unsigned int device) -{ - unsigned int n = user + USERHASH*(file + FILEHASH*device); - - // June 7th, 2006 - static struct rtc_time time = { - .tm_sec = 0, - .tm_min = 0, - .tm_hour = 0, - .tm_mday = 7, - .tm_mon = 5, // June - counting from zero - .tm_year = 106, - .tm_wday = 3, - .tm_yday = 160, - .tm_isdst = 1 - }; - - time.tm_year = (n % 100); - n /= 100; - time.tm_mon = (n % 12); - n /= 12; - time.tm_mday = (n % 28) + 1; - n /= 28; - time.tm_hour = (n % 24); - n /= 24; - time.tm_min = (n % 20) * 3; - n /= 20; - set_rtc_time(&time); - return n ? -1 : 0; -} - -static unsigned int read_magic_time(void) -{ - struct rtc_time time; - unsigned int val; - - get_rtc_time(&time); - printk("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n", - time.tm_hour, time.tm_min, time.tm_sec, - time.tm_mon, time.tm_mday, time.tm_year); - val = time.tm_year; /* 100 years */ - if (val > 100) - val -= 100; - val += time.tm_mon * 100; /* 12 months */ - val += (time.tm_mday-1) * 100 * 12; /* 28 month-days */ - val += time.tm_hour * 100 * 12 * 28; /* 24 hours */ - val += (time.tm_min / 3) * 100 * 12 * 28 * 24; /* 20 3-minute intervals */ - return val; -} - -/* - * This is just the sdbm hash function with a user-supplied - * seed and final size parameter. - */ -static unsigned int hash_string(unsigned int seed, const char *data, unsigned int mod) -{ - unsigned char c; - while ((c = *data++) != 0) { - seed = (seed << 16) + (seed << 6) - seed + c; - } - return seed % mod; -} - -void set_trace_device(struct device *dev) -{ - dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH); -} - -/* - * We could just take the "tracedata" index into the .tracedata - * section instead. Generating a hash of the data gives us a - * chance to work across kernel versions, and perhaps more - * importantly it also gives us valid/invalid check (ie we will - * likely not give totally bogus reports - if the hash matches, - * it's not any guarantee, but it's a high _likelihood_ that - * the match is valid). - */ -void generate_resume_trace(void *tracedata, unsigned int user) -{ - unsigned short lineno = *(unsigned short *)tracedata; - const char *file = *(const char **)(tracedata + 2); - unsigned int user_hash_value, file_hash_value; - - user_hash_value = user % USERHASH; - file_hash_value = hash_string(lineno, file, FILEHASH); - set_magic_time(user_hash_value, file_hash_value, dev_hash_value); -} - -extern char __tracedata_start, __tracedata_end; -static int show_file_hash(unsigned int value) -{ - int match; - char *tracedata; - - match = 0; - for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) { - unsigned short lineno = *(unsigned short *)tracedata; - const char *file = *(const char **)(tracedata + 2); - unsigned int hash = hash_string(lineno, file, FILEHASH); - if (hash != value) - continue; - printk(" hash matches %s:%u\n", file, lineno); - match++; - } - return match; -} - -static int show_dev_hash(unsigned int value) -{ - int match = 0; - struct list_head * entry = dpm_active.prev; - - while (entry != &dpm_active) { - struct device * dev = to_device(entry); - unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); - if (hash == value) { - printk(" hash matches device %s\n", dev->bus_id); - match++; - } - entry = entry->prev; - } - return match; -} - -static unsigned int hash_value_early_read; - -static int early_resume_init(void) -{ - hash_value_early_read = read_magic_time(); - return 0; -} - -static int late_resume_init(void) -{ - unsigned int val = hash_value_early_read; - unsigned int user, file, dev; - - user = val % USERHASH; - val = val / USERHASH; - file = val % FILEHASH; - val = val / FILEHASH; - dev = val /* % DEVHASH */; - - printk(" Magic number: %d:%d:%d\n", user, file, dev); - show_file_hash(file); - show_dev_hash(dev); - return 0; -} - -core_initcall(early_resume_init); -late_initcall(late_resume_init); diff --git a/trunk/drivers/sbus/sbus.c b/trunk/drivers/sbus/sbus.c index 5d30a3ebfccd..6e9b2608202b 100644 --- a/trunk/drivers/sbus/sbus.c +++ b/trunk/drivers/sbus/sbus.c @@ -1,7 +1,6 @@ -/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $ - * sbus.c: SBus support routines. +/* sbus.c: SBus support routines. * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) */ #include @@ -17,29 +16,12 @@ #include #include -struct sbus_bus *sbus_root = NULL; - -static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } }; -#ifdef CONFIG_SPARC32 -static int interrupts[PROMINTR_MAX] __initdata = { 0 }; -#endif +struct sbus_bus *sbus_root; #ifdef CONFIG_PCI extern int pcic_present(void); #endif -/* Perhaps when I figure out more about the iommu we'll put a - * device registration routine here that probe_sbus() calls to - * setup the iommu for each Sbus. - */ - -/* We call this for each SBus device, and fill the structure based - * upon the prom device tree. We return the start of memory after - * the things we have allocated. - */ - -/* #define DEBUG_FILL */ - static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) { unsigned long address, base; @@ -52,117 +34,30 @@ static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev) len = prom_getproperty(prom_node, "reg", (char *) sdev->reg_addrs, sizeof(sdev->reg_addrs)); - if (len == -1) { - sdev->num_registers = 0; - goto no_regs; - } - - if (len % sizeof(struct linux_prom_registers)) { - prom_printf("fill_sbus_device: proplen for regs of %s " - " was %d, need multiple of %d\n", - sdev->prom_name, len, - (int) sizeof(struct linux_prom_registers)); - prom_halt(); - } - if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) { - prom_printf("fill_sbus_device: Too many register properties " - "for device %s, len=%d\n", - sdev->prom_name, len); - prom_halt(); - } - sdev->num_registers = len / sizeof(struct linux_prom_registers); - sdev->ranges_applied = 0; + sdev->num_registers = 0; + if (len != -1) { + sdev->num_registers = + len / sizeof(struct linux_prom_registers); + sdev->ranges_applied = 0; - base = (unsigned long) sdev->reg_addrs[0].phys_addr; + base = (unsigned long) sdev->reg_addrs[0].phys_addr; - /* Compute the slot number. */ - if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) { - sdev->slot = sbus_dev_slot(base); - } else { - sdev->slot = sdev->reg_addrs[0].which_io; + /* Compute the slot number. */ + if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) + sdev->slot = sbus_dev_slot(base); + else + sdev->slot = sdev->reg_addrs[0].which_io; } -no_regs: len = prom_getproperty(prom_node, "ranges", (char *)sdev->device_ranges, sizeof(sdev->device_ranges)); - if (len == -1) { - sdev->num_device_ranges = 0; - goto no_ranges; - } - if (len % sizeof(struct linux_prom_ranges)) { - prom_printf("fill_sbus_device: proplen for ranges of %s " - " was %d, need multiple of %d\n", - sdev->prom_name, len, - (int) sizeof(struct linux_prom_ranges)); - prom_halt(); - } - if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) { - prom_printf("fill_sbus_device: Too many range properties " - "for device %s, len=%d\n", - sdev->prom_name, len); - prom_halt(); - } - sdev->num_device_ranges = - len / sizeof(struct linux_prom_ranges); + sdev->num_device_ranges = 0; + if (len != -1) + sdev->num_device_ranges = + len / sizeof(struct linux_prom_ranges); -no_ranges: - /* XXX Unfortunately, IRQ issues are very arch specific. - * XXX Pull this crud out into an arch specific area - * XXX at some point. -DaveM - */ -#ifdef CONFIG_SPARC64 - len = prom_getproperty(prom_node, "interrupts", - (char *) irqs, sizeof(irqs)); - if (len == -1 || len == 0) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - unsigned int pri = irqs[0].pri; - - sdev->num_irqs = 1; - if (pri < 0x20) - pri += sdev->slot * 8; - - sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); - } -#endif /* CONFIG_SPARC64 */ - -#ifdef CONFIG_SPARC32 - len = prom_getproperty(prom_node, "intr", - (char *)irqs, sizeof(irqs)); - if (len != -1) { - sdev->num_irqs = len / 8; - if (sdev->num_irqs == 0) { - sdev->irqs[0] = 0; - } else if (sparc_cpu_model == sun4d) { - extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); - - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri); - } else { - for (len = 0; len < sdev->num_irqs; len++) - sdev->irqs[len] = irqs[len].pri; - } - } else { - /* No "intr" node found-- check for "interrupts" node. - * This node contains SBus interrupt levels, not IPLs - * as in "intr", and no vector values. We convert - * SBus interrupt levels to PILs (platform specific). - */ - len = prom_getproperty(prom_node, "interrupts", - (char *)interrupts, sizeof(interrupts)); - if (len == -1) { - sdev->irqs[0] = 0; - sdev->num_irqs = 0; - } else { - sdev->num_irqs = len / sizeof(int); - for (len = 0; len < sdev->num_irqs; len++) { - sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]); - } - } - } -#endif /* CONFIG_SPARC32 */ + sbus_fill_device_irq(sdev); } /* This routine gets called from whoever needs the sbus first, to scan diff --git a/trunk/include/asm-generic/rtc.h b/trunk/include/asm-generic/rtc.h index 4087037a4225..cef08db34ada 100644 --- a/trunk/include/asm-generic/rtc.h +++ b/trunk/include/asm-generic/rtc.h @@ -114,7 +114,6 @@ static inline unsigned int get_rtc_time(struct rtc_time *time) /* Set the current date and time in the real time clock. */ static inline int set_rtc_time(struct rtc_time *time) { - unsigned long flags; unsigned char mon, day, hrs, min, sec; unsigned char save_control, save_freq_select; unsigned int yrs; @@ -132,7 +131,7 @@ static inline int set_rtc_time(struct rtc_time *time) if (yrs > 255) /* They are unsigned */ return -EINVAL; - spin_lock_irqsave(&rtc_lock, flags); + spin_lock_irq(&rtc_lock); #ifdef CONFIG_MACH_DECSTATION real_yrs = yrs; leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || @@ -153,7 +152,7 @@ static inline int set_rtc_time(struct rtc_time *time) * whether the chip is in binary mode or not. */ if (yrs > 169) { - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irq(&rtc_lock); return -EINVAL; } @@ -188,7 +187,7 @@ static inline int set_rtc_time(struct rtc_time *time) CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock_irqrestore(&rtc_lock, flags); + spin_unlock_irq(&rtc_lock); return 0; } diff --git a/trunk/include/asm-sparc/sbus.h b/trunk/include/asm-sparc/sbus.h index a13cddcecec5..76654fa23091 100644 --- a/trunk/include/asm-sparc/sbus.h +++ b/trunk/include/asm-sparc/sbus.h @@ -102,6 +102,7 @@ sbus_is_slave(struct sbus_dev *dev) #define sbus_can_dma_64bit(sdev) (0) /* actually, sparc_cpu_model==sun4d */ #define sbus_can_burst64(sdev) (0) /* actually, sparc_cpu_model==sun4d */ extern void sbus_set_sbus64(struct sbus_dev *, int); +extern void sbus_fill_device_irq(struct sbus_dev *); /* These yield IOMMU mappings in consistent mode. */ extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); diff --git a/trunk/include/asm-sparc64/sbus.h b/trunk/include/asm-sparc64/sbus.h index 48279e10f385..ca2054da2430 100644 --- a/trunk/include/asm-sparc64/sbus.h +++ b/trunk/include/asm-sparc64/sbus.h @@ -95,6 +95,7 @@ extern struct sbus_bus *sbus_root; #define sbus_can_dma_64bit(sdev) (1) #define sbus_can_burst64(sdev) (1) extern void sbus_set_sbus64(struct sbus_dev *, int); +extern void sbus_fill_device_irq(struct sbus_dev *); /* These yield IOMMU mappings in consistent mode. */ extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp); diff --git a/trunk/include/linux/resume-trace.h b/trunk/include/linux/resume-trace.h deleted file mode 100644 index a376bd4ade39..000000000000 --- a/trunk/include/linux/resume-trace.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RESUME_TRACE_H -#define RESUME_TRACE_H - -#ifdef CONFIG_PM_TRACE - -struct device; -extern void set_trace_device(struct device *); -extern void generate_resume_trace(void *tracedata, unsigned int user); - -#define TRACE_DEVICE(dev) set_trace_device(dev) -#define TRACE_RESUME(user) do { \ - void *tracedata; \ - asm volatile("movl $1f,%0\n" \ - ".section .tracedata,\"a\"\n" \ - "1:\t.word %c1\n" \ - "\t.long %c2\n" \ - ".previous" \ - :"=r" (tracedata) \ - : "i" (__LINE__), "i" (__FILE__)); \ - generate_resume_trace(tracedata, user); \ -} while (0) - -#else - -#define TRACE_DEVICE(dev) do { } while (0) -#define TRACE_RESUME(dev) do { } while (0) - -#endif - -#endif diff --git a/trunk/kernel/power/Kconfig b/trunk/kernel/power/Kconfig index cdf315e794ff..ce0dfb8f4a4e 100644 --- a/trunk/kernel/power/Kconfig +++ b/trunk/kernel/power/Kconfig @@ -36,15 +36,6 @@ config PM_DEBUG code. This is helpful when debugging and reporting various PM bugs, like suspend support. -config PM_TRACE - bool "Suspend/resume event tracing" - depends on PM && PM_DEBUG && X86 - default y - ---help--- - This enables some cheesy code to save the last PM event point in the - RTC across reboots, so that you can debug a machine that just hangs - during suspend (or more commonly, during resume). - config SOFTWARE_SUSPEND bool "Software Suspend" depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)