From 0bb77c465f02e8281e24b9f02e7dc8a7e2b81ee2 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Mon, 3 Jan 2011 14:22:11 -0800 Subject: pstore: X86 platform interface using ACPI/APEI/ERST The 'error record serialization table' in ACPI provides a suitable amount of persistent storage for use by the pstore filesystem. Signed-off-by: Tony Luck --- drivers/acpi/apei/Kconfig | 1 + drivers/acpi/apei/erst.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index fca34ccfd294..e91680c7e047 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -1,5 +1,6 @@ config ACPI_APEI bool "ACPI Platform Error Interface (APEI)" + select PSTORE depends on X86 help APEI allows to report errors (for example from the chipset) diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 5850d320404c..22d70dbe75d1 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "apei-internal.h" @@ -781,6 +782,128 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) return 0; } +static size_t erst_reader(u64 *id, enum pstore_type_id *type, + struct timespec *time); +static u64 erst_writer(enum pstore_type_id type, size_t size); + +static struct pstore_info erst_info = { + .owner = THIS_MODULE, + .name = "erst", + .read = erst_reader, + .write = erst_writer, + .erase = erst_clear +}; + +#define CPER_CREATOR_PSTORE \ + UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c, \ + 0x64, 0x90, 0xb8, 0x9d) +#define CPER_SECTION_TYPE_DMESG \ + UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54, \ + 0x94, 0x19, 0xeb, 0x12) +#define CPER_SECTION_TYPE_MCE \ + UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96, \ + 0x04, 0x4a, 0x38, 0xfc) + +struct cper_pstore_record { + struct cper_record_header hdr; + struct cper_section_descriptor sec_hdr; + char data[]; +} __packed; + +static size_t erst_reader(u64 *id, enum pstore_type_id *type, + struct timespec *time) +{ + int rc; + ssize_t len; + unsigned long flags; + u64 record_id; + struct cper_pstore_record *rcd = (struct cper_pstore_record *) + (erst_info.buf - sizeof(*rcd)); + + if (erst_disable) + return -ENODEV; + + raw_spin_lock_irqsave(&erst_lock, flags); +skip: + rc = __erst_get_next_record_id(&record_id); + if (rc) { + raw_spin_unlock_irqrestore(&erst_lock, flags); + return rc; + } + /* no more record */ + if (record_id == APEI_ERST_INVALID_RECORD_ID) { + raw_spin_unlock_irqrestore(&erst_lock, flags); + return 0; + } + + len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) + + erst_erange.size); + if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) + goto skip; + raw_spin_unlock_irqrestore(&erst_lock, flags); + + *id = record_id; + if (uuid_le_cmp(rcd->sec_hdr.section_type, + CPER_SECTION_TYPE_DMESG) == 0) + *type = PSTORE_TYPE_DMESG; + else if (uuid_le_cmp(rcd->sec_hdr.section_type, + CPER_SECTION_TYPE_MCE) == 0) + *type = PSTORE_TYPE_MCE; + else + *type = PSTORE_TYPE_UNKNOWN; + + if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP) + time->tv_sec = rcd->hdr.timestamp; + else + time->tv_sec = 0; + time->tv_nsec = 0; + + return len - sizeof(*rcd); +} + +static u64 erst_writer(enum pstore_type_id type, size_t size) +{ + struct cper_pstore_record *rcd = (struct cper_pstore_record *) + (erst_info.buf - sizeof(*rcd)); + + memset(rcd, 0, sizeof(*rcd)); + memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE); + rcd->hdr.revision = CPER_RECORD_REV; + rcd->hdr.signature_end = CPER_SIG_END; + rcd->hdr.section_count = 1; + rcd->hdr.error_severity = CPER_SEV_FATAL; + /* timestamp valid. platform_id, partition_id are invalid */ + rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP; + rcd->hdr.timestamp = get_seconds(); + rcd->hdr.record_length = sizeof(*rcd) + size; + rcd->hdr.creator_id = CPER_CREATOR_PSTORE; + rcd->hdr.notification_type = CPER_NOTIFY_MCE; + rcd->hdr.record_id = cper_next_record_id(); + rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR; + + rcd->sec_hdr.section_offset = sizeof(*rcd); + rcd->sec_hdr.section_length = size; + rcd->sec_hdr.revision = CPER_SEC_REV; + /* fru_id and fru_text is invalid */ + rcd->sec_hdr.validation_bits = 0; + rcd->sec_hdr.flags = CPER_SEC_PRIMARY; + switch (type) { + case PSTORE_TYPE_DMESG: + rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG; + break; + case PSTORE_TYPE_MCE: + rcd->sec_hdr.section_type = CPER_SECTION_TYPE_MCE; + break; + default: + return -EINVAL; + } + rcd->sec_hdr.section_severity = CPER_SEV_FATAL; + + erst_write(&rcd->hdr); + + return rcd->hdr.record_id; +} + static int __init erst_init(void) { int rc = 0; @@ -788,6 +911,7 @@ static int __init erst_init(void) struct apei_exec_context ctx; struct apei_resources erst_resources; struct resource *r; + char *buf; if (acpi_disabled) goto err; @@ -854,6 +978,18 @@ static int __init erst_init(void) if (!erst_erange.vaddr) goto err_release_erange; + buf = kmalloc(erst_erange.size, GFP_KERNEL); + mutex_init(&erst_info.buf_mutex); + if (buf) { + erst_info.buf = buf + sizeof(struct cper_pstore_record); + erst_info.bufsize = erst_erange.size - + sizeof(struct cper_pstore_record); + if (pstore_register(&erst_info)) { + pr_info(ERST_PFX "Could not register with persistent store\n"); + kfree(buf); + } + } + pr_info(ERST_PFX "Error Record Serialization Table (ERST) support is initialized.\n"); -- cgit v1.2.3 From 44d2588e1102b4e35022d03b7f124dd6ea013ce8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 1 Feb 2011 11:42:42 +0100 Subject: acpi: kacpi*_wq don't need WQ_MEM_RECLAIM ACPI workqueues aren't used during memory reclaming. Use alloc_workqueue() to create workqueues w/o rescuers. If the purpose of the separation between kacpid_wq and kacpi_notify_wq was to give notifications better response time, kacpi_notify_wq can be dropped and kacpi_wq can be created with higher @max_active. Signed-off-by: Tejun Heo Cc: Len Brown Cc: linux-acpi@vger.kernel.org --- drivers/acpi/osl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b0931818cf98..60a80cbfcdc7 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1578,9 +1578,9 @@ acpi_status __init acpi_os_initialize(void) acpi_status __init acpi_os_initialize1(void) { - kacpid_wq = create_workqueue("kacpid"); - kacpi_notify_wq = create_workqueue("kacpi_notify"); - kacpi_hotplug_wq = create_workqueue("kacpi_hotplug"); + kacpid_wq = alloc_workqueue("kacpid", 0, 1); + kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); + kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1); BUG_ON(!kacpid_wq); BUG_ON(!kacpi_notify_wq); BUG_ON(!kacpi_hotplug_wq); -- cgit v1.2.3 From 940fed2e79a15cf0d006c860d7811adbe5c19882 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 16 Feb 2011 12:13:06 +0100 Subject: x86-64, NUMA: Unify {acpi|amd}_{numa_init|scan_nodes}() arguments and return values The functions used during NUMA initialization - *_numa_init() and *_scan_nodes() - have different arguments and return values. Unify them such that they all take no argument and return 0 on success and -errno on failure. This is in preparation for further NUMA init cleanups. Signed-off-by: Tejun Heo Cc: Yinghai Lu Cc: Brian Gerst Cc: Cyrill Gorcunov Cc: Shaohui Zheng Cc: David Rientjes Cc: Ingo Molnar Cc: H. Peter Anvin --- arch/x86/include/asm/acpi.h | 2 +- arch/x86/include/asm/amd_nb.h | 2 +- arch/x86/kernel/setup.c | 4 ++-- arch/x86/mm/amdtopology_64.c | 18 +++++++++--------- arch/x86/mm/numa_64.c | 2 +- arch/x86/mm/srat_64.c | 4 ++-- drivers/acpi/numa.c | 9 ++++++--- 7 files changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 211ca3f7fd16..4e5dff9e0b39 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -187,7 +187,7 @@ struct bootnode; extern int acpi_numa; extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start, unsigned long end); -extern int acpi_scan_nodes(unsigned long start, unsigned long end); +extern int acpi_scan_nodes(void); #define NR_NODE_MEMBLKS (MAX_NUMNODES*2) #ifdef CONFIG_NUMA_EMU diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index 2b33c4df979f..dc3c6e34da1d 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h @@ -16,7 +16,7 @@ struct bootnode; extern int early_is_amd_nb(u32 value); extern int amd_cache_northbridges(void); extern void amd_flush_garts(void); -extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn); +extern int amd_numa_init(void); extern int amd_scan_nodes(void); extern int amd_get_subcaches(int); extern int amd_set_subcaches(int, int); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 756d640723f9..96810a3c6003 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -995,12 +995,12 @@ void __init setup_arch(char **cmdline_p) /* * Parse SRAT to discover nodes. */ - acpi = acpi_numa_init(); + acpi = !acpi_numa_init(); #endif #ifdef CONFIG_AMD_NUMA if (!acpi) - amd = !amd_numa_init(0, max_pfn); + amd = !amd_numa_init(); #endif initmem_init(acpi, amd); diff --git a/arch/x86/mm/amdtopology_64.c b/arch/x86/mm/amdtopology_64.c index 2523c3554de5..655ccffc6ee5 100644 --- a/arch/x86/mm/amdtopology_64.c +++ b/arch/x86/mm/amdtopology_64.c @@ -51,7 +51,7 @@ static __init int find_northbridge(void) return num; } - return -1; + return -ENOENT; } static __init void early_get_boot_cpu_id(void) @@ -69,17 +69,17 @@ static __init void early_get_boot_cpu_id(void) #endif } -int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) +int __init amd_numa_init(void) { - unsigned long start = PFN_PHYS(start_pfn); - unsigned long end = PFN_PHYS(end_pfn); + unsigned long start = PFN_PHYS(0); + unsigned long end = PFN_PHYS(max_pfn); unsigned numnodes; unsigned long prevbase; int i, nb, found = 0; u32 nodeid, reg; if (!early_pci_allowed()) - return -1; + return -EINVAL; nb = find_northbridge(); if (nb < 0) @@ -90,7 +90,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) reg = read_pci_config(0, nb, 0, 0x60); numnodes = ((reg >> 4) & 0xF) + 1; if (numnodes <= 1) - return -1; + return -ENOENT; pr_info("Number of physical nodes %d\n", numnodes); @@ -121,7 +121,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) if ((base >> 8) & 3 || (limit >> 8) & 3) { pr_err("Node %d using interleaving mode %lx/%lx\n", nodeid, (base >> 8) & 3, (limit >> 8) & 3); - return -1; + return -EINVAL; } if (node_isset(nodeid, nodes_parsed)) { pr_info("Node %d already present, skipping\n", @@ -160,7 +160,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) if (prevbase > base) { pr_err("Node map not sorted %lx,%lx\n", prevbase, base); - return -1; + return -EINVAL; } pr_info("Node %d MemBase %016lx Limit %016lx\n", @@ -177,7 +177,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) } if (!found) - return -1; + return -ENOENT; return 0; } diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index d7e4aafd0759..a083f515f004 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -596,7 +596,7 @@ void __init initmem_init(int acpi, int amd) #endif #ifdef CONFIG_ACPI_NUMA - if (!numa_off && acpi && !acpi_scan_nodes(0, max_pfn << PAGE_SHIFT)) + if (!numa_off && acpi && !acpi_scan_nodes()) return; nodes_clear(node_possible_map); nodes_clear(node_online_map); diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 988b0b70ff39..4f9dbf066ca4 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -359,7 +359,7 @@ void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start, #endif /* CONFIG_NUMA_EMU */ /* Use the information discovered above to actually set up the nodes. */ -int __init acpi_scan_nodes(unsigned long start, unsigned long end) +int __init acpi_scan_nodes(void) { int i; @@ -368,7 +368,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) /* First clean up the node list */ for (i = 0; i < MAX_NUMNODES; i++) - cutoff_node(i, start, end); + cutoff_node(i, 0, max_pfn << PAGE_SHIFT); /* * Join together blocks on the same node, holes between diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 5eb25eb3ea48..3b5c3189fd99 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -274,7 +274,7 @@ acpi_table_parse_srat(enum acpi_srat_type id, int __init acpi_numa_init(void) { - int ret = 0; + int cnt = 0; /* * Should not limit number with cpu num that is from NR_CPUS or nr_cpus= @@ -288,7 +288,7 @@ int __init acpi_numa_init(void) acpi_parse_x2apic_affinity, 0); acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, acpi_parse_processor_affinity, 0); - ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, + cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); } @@ -297,7 +297,10 @@ int __init acpi_numa_init(void) acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); acpi_numa_arch_fixup(); - return ret; + + if (cnt <= 0) + return cnt ?: -ENOENT; + return 0; } int acpi_get_pxm(acpi_handle h) -- cgit v1.2.3 From d1ee433539ea5963a8f946f3428b335d1c5fdb20 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 14 Feb 2011 15:42:46 -0800 Subject: x86, trampoline: Use the unified trampoline setup for ACPI wakeup Use the unified trampoline allocation setup to allocate and install the ACPI wakeup code in low memory. Signed-off-by: H. Peter Anvin LKML-Reference: <4D5DFBE4.7090104@intel.com> Cc: Rafael J. Wysocki Cc: Matthieu Castet Cc: Stephen Rothwell --- arch/x86/include/asm/acpi.h | 4 +- arch/x86/include/asm/trampoline.h | 33 ++++++++++----- arch/x86/kernel/acpi/realmode/wakeup.S | 21 ++++++---- arch/x86/kernel/acpi/realmode/wakeup.h | 5 ++- arch/x86/kernel/acpi/realmode/wakeup.lds.S | 28 ++++++------- arch/x86/kernel/acpi/sleep.c | 65 ++++-------------------------- arch/x86/kernel/acpi/sleep.h | 3 -- arch/x86/kernel/acpi/wakeup_rm.S | 10 +++-- arch/x86/kernel/setup.c | 7 ---- drivers/acpi/sleep.c | 1 + 10 files changed, 69 insertions(+), 108 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 211ca3f7fd16..4784df504d28 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -29,6 +29,7 @@ #include #include #include +#include #define COMPILER_DEPENDENT_INT64 long long #define COMPILER_DEPENDENT_UINT64 unsigned long long @@ -116,7 +117,8 @@ static inline void acpi_disable_pci(void) extern int acpi_save_state_mem(void); extern void acpi_restore_state_mem(void); -extern unsigned long acpi_wakeup_address; +extern const unsigned char acpi_wakeup_code[]; +#define acpi_wakeup_address (__pa(TRAMPOLINE_SYM(acpi_wakeup_code))) /* early initialization routine */ extern void acpi_reserve_wakeup_memory(void); diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h index f4500fb3b485..feca3118a73b 100644 --- a/arch/x86/include/asm/trampoline.h +++ b/arch/x86/include/asm/trampoline.h @@ -3,25 +3,36 @@ #ifndef __ASSEMBLY__ -#ifdef CONFIG_X86_TRAMPOLINE +#include +#include + /* - * Trampoline 80x86 program as an array. + * Trampoline 80x86 program as an array. These are in the init rodata + * segment, but that's okay, because we only care about the relative + * addresses of the symbols. */ -extern const unsigned char trampoline_data []; -extern const unsigned char trampoline_end []; -extern unsigned char *trampoline_base; +extern const unsigned char x86_trampoline_start []; +extern const unsigned char x86_trampoline_end []; +extern unsigned char *x86_trampoline_base; extern unsigned long init_rsp; extern unsigned long initial_code; extern unsigned long initial_gs; -#define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE) +extern void __init setup_trampolines(void); + +extern const unsigned char trampoline_data[]; +extern const unsigned char trampoline_status[]; + +#define TRAMPOLINE_SYM(x) \ + ((void *)(x86_trampoline_base + \ + ((const unsigned char *)(x) - x86_trampoline_start))) -extern unsigned long setup_trampoline(void); -extern void __init reserve_trampoline_memory(void); -#else -static inline void reserve_trampoline_memory(void) {} -#endif /* CONFIG_X86_TRAMPOLINE */ +/* Address of the SMP trampoline */ +static inline unsigned long trampoline_address(void) +{ + return virt_to_phys(TRAMPOLINE_SYM(trampoline_data)); +} #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S index 28595d6df47c..ead21b663117 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.S +++ b/arch/x86/kernel/acpi/realmode/wakeup.S @@ -6,11 +6,17 @@ #include #include #include +#include "wakeup.h" .code16 - .section ".header", "a" + .section ".jump", "ax" + .globl _start +_start: + cli + jmp wakeup_code /* This should match the structure in wakeup.h */ + .section ".header", "a" .globl wakeup_header wakeup_header: video_mode: .short 0 /* Video mode number */ @@ -30,14 +36,11 @@ wakeup_jmp: .byte 0xea /* ljmpw */ wakeup_jmp_off: .word 3f wakeup_jmp_seg: .word 0 wakeup_gdt: .quad 0, 0, 0 -signature: .long 0x51ee1111 +signature: .long WAKEUP_HEADER_SIGNATURE .text - .globl _start .code16 wakeup_code: -_start: - cli cld /* Apparently some dimwit BIOS programmers don't know how to @@ -77,12 +80,12 @@ _start: /* Check header signature... */ movl signature, %eax - cmpl $0x51ee1111, %eax + cmpl $WAKEUP_HEADER_SIGNATURE, %eax jne bogus_real_magic /* Check we really have everything... */ movl end_signature, %eax - cmpl $0x65a22c82, %eax + cmpl $WAKEUP_END_SIGNATURE, %eax jne bogus_real_magic /* Call the C code */ @@ -147,3 +150,7 @@ wakeup_heap: wakeup_stack: .space 2048 wakeup_stack_end: + + .section ".signature","a" +end_signature: + .long WAKEUP_END_SIGNATURE diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h index 69d38d0b2b64..e1828c07e79c 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.h +++ b/arch/x86/kernel/acpi/realmode/wakeup.h @@ -35,7 +35,8 @@ struct wakeup_header { extern struct wakeup_header wakeup_header; #endif -#define HEADER_OFFSET 0x3f00 -#define WAKEUP_SIZE 0x4000 +#define WAKEUP_HEADER_OFFSET 8 +#define WAKEUP_HEADER_SIGNATURE 0x51ee1111 +#define WAKEUP_END_SIGNATURE 0x65a22c82 #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */ diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S index 060fff8f5c5b..d4f8010a5b1b 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.lds.S +++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S @@ -13,9 +13,19 @@ ENTRY(_start) SECTIONS { . = 0; + .jump : { + *(.jump) + } = 0x90909090 + + . = WAKEUP_HEADER_OFFSET; + .header : { + *(.header) + } + + . = ALIGN(16); .text : { *(.text*) - } + } = 0x90909090 . = ALIGN(16); .rodata : { @@ -33,11 +43,6 @@ SECTIONS *(.data*) } - .signature : { - end_signature = .; - LONG(0x65a22c82) - } - . = ALIGN(16); .bss : { __bss_start = .; @@ -45,20 +50,13 @@ SECTIONS __bss_end = .; } - . = HEADER_OFFSET; - .header : { - *(.header) + .signature : { + *(.signature) } - . = ALIGN(16); _end = .; /DISCARD/ : { *(.note*) } - - /* - * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility: - */ - . = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!"); } diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 68d1537b8c81..4572c58e66d5 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -18,12 +18,8 @@ #include "realmode/wakeup.h" #include "sleep.h" -unsigned long acpi_wakeup_address; unsigned long acpi_realmode_flags; -/* address in low memory of the wakeup routine. */ -static unsigned long acpi_realmode; - #if defined(CONFIG_SMP) && defined(CONFIG_64BIT) static char temp_stack[4096]; #endif @@ -33,22 +29,17 @@ static char temp_stack[4096]; * * Create an identity mapped page table and copy the wakeup routine to * low memory. - * - * Note that this is too late to change acpi_wakeup_address. */ int acpi_save_state_mem(void) { struct wakeup_header *header; + /* address in low memory of the wakeup routine. */ + char *acpi_realmode; - if (!acpi_realmode) { - printk(KERN_ERR "Could not allocate memory during boot, " - "S3 disabled\n"); - return -ENOMEM; - } - memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE); + acpi_realmode = TRAMPOLINE_SYM(acpi_wakeup_code); - header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET); - if (header->signature != 0x51ee1111) { + header = (struct wakeup_header *)(acpi_realmode + WAKEUP_HEADER_OFFSET); + if (header->signature != WAKEUP_HEADER_SIGNATURE) { printk(KERN_ERR "wakeup header does not match\n"); return -EINVAL; } @@ -68,9 +59,7 @@ int acpi_save_state_mem(void) /* GDT[0]: GDT self-pointer */ header->wakeup_gdt[0] = (u64)(sizeof(header->wakeup_gdt) - 1) + - ((u64)(acpi_wakeup_address + - ((char *)&header->wakeup_gdt - (char *)acpi_realmode)) - << 16); + ((u64)__pa(&header->wakeup_gdt) << 16); /* GDT[1]: big real mode-like code segment */ header->wakeup_gdt[1] = GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff); @@ -96,7 +85,7 @@ int acpi_save_state_mem(void) header->pmode_cr3 = (u32)__pa(&initial_page_table); saved_magic = 0x12345678; #else /* CONFIG_64BIT */ - header->trampoline_segment = setup_trampoline() >> 4; + header->trampoline_segment = trampoline_address() >> 4; #ifdef CONFIG_SMP stack_start = (unsigned long)temp_stack + sizeof(temp_stack); early_gdt_descr.address = @@ -117,46 +106,6 @@ void acpi_restore_state_mem(void) { } - -/** - * acpi_reserve_wakeup_memory - do _very_ early ACPI initialisation - * - * We allocate a page from the first 1MB of memory for the wakeup - * routine for when we come back from a sleep state. The - * runtime allocator allows specification of <16MB pages, but not - * <1MB pages. - */ -void __init acpi_reserve_wakeup_memory(void) -{ - phys_addr_t mem; - - if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) { - printk(KERN_ERR - "ACPI: Wakeup code way too big, S3 disabled.\n"); - return; - } - - mem = memblock_find_in_range(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE); - - if (mem == MEMBLOCK_ERROR) { - printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n"); - return; - } - acpi_realmode = (unsigned long) phys_to_virt(mem); - acpi_wakeup_address = mem; - memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP"); -} - -int __init acpi_configure_wakeup_memory(void) -{ - if (acpi_realmode) - set_memory_x(acpi_realmode, WAKEUP_SIZE >> PAGE_SHIFT); - - return 0; -} -arch_initcall(acpi_configure_wakeup_memory); - - static int __init acpi_sleep_setup(char *str) { while ((str != NULL) && (*str != '\0')) { diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index adbcbaa6f1df..86ba1c87165b 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -4,13 +4,10 @@ #include -extern char wakeup_code_start, wakeup_code_end; - extern unsigned long saved_video_mode; extern long saved_magic; extern int wakeup_pmode_return; -extern char swsusp_pg_dir[PAGE_SIZE]; extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S index 6ff3b5730575..6ce81ee9cb03 100644 --- a/arch/x86/kernel/acpi/wakeup_rm.S +++ b/arch/x86/kernel/acpi/wakeup_rm.S @@ -2,9 +2,11 @@ * Wrapper script for the realmode binary as a transport object * before copying to low memory. */ - .section ".rodata","a" - .globl wakeup_code_start, wakeup_code_end -wakeup_code_start: +#include + + .section ".x86_trampoline","a" + .balign PAGE_SIZE + .globl acpi_wakeup_code +acpi_wakeup_code: .incbin "arch/x86/kernel/acpi/realmode/wakeup.bin" -wakeup_code_end: .size wakeup_code_start, .-wakeup_code_start diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 994ea20e177c..a089fc19ffae 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -937,13 +937,6 @@ void __init setup_arch(char **cmdline_p) setup_trampolines(); -#ifdef CONFIG_ACPI_SLEEP - /* - * Reserve low memory region for sleep support. - * even before init_memory_mapping - */ - acpi_reserve_wakeup_memory(); -#endif init_gbpages(); /* max_pfn_mapped is updated here */ diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index d6a8cd14de2e..e9fef94d1039 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -16,6 +16,7 @@ #include #include #include +#include #include -- cgit v1.2.3 From cd51e61cf4e8b220da37dc35e9c2dc2dc258b4de Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 11 Feb 2011 00:04:52 +0100 Subject: PM / ACPI: Remove references to pm_flags from bus.c If direct references to pm_flags are removed from drivers/acpi/bus.c, CONFIG_ACPI will not need to depend on CONFIG_PM any more. Make that happen. Signed-off-by: Rafael J. Wysocki Acked-by: Len Brown --- drivers/acpi/Kconfig | 1 - drivers/acpi/bus.c | 7 ++++--- include/linux/suspend.h | 6 ++++++ kernel/power/main.c | 12 +++++++++++- 4 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 2aa042a5da6d..3a17ca5fff6f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -7,7 +7,6 @@ menuconfig ACPI depends on !IA64_HP_SIM depends on IA64 || X86 depends on PCI - depends on PM select PNP default y help diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7ced61f39492..973b0709972c 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "internal.h" @@ -1025,13 +1026,13 @@ static int __init acpi_init(void) if (!result) { pci_mmcfg_late_init(); - if (!(pm_flags & PM_APM)) - pm_flags |= PM_ACPI; - else { + if (pm_apm_enabled()) { printk(KERN_INFO PREFIX "APM is already active, exiting\n"); disable_acpi(); result = -ENODEV; + } else { + pm_set_acpi_flag(); } } else disable_acpi(); diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5a89e3612875..5e364db8a56a 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -272,6 +272,9 @@ extern int unregister_pm_notifier(struct notifier_block *nb); register_pm_notifier(&fn##_nb); \ } +extern bool pm_apm_enabled(void); +extern void pm_set_acpi_flag(void); + /* drivers/base/power/wakeup.c */ extern bool events_check_enabled; @@ -292,6 +295,9 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) #define pm_notifier(fn, pri) do { (void)(fn); } while (0) +static inline bool pm_apm_enabled(void) { return false; } +static inline void pm_set_acpi_flag(void) {} + static inline bool pm_wakeup_pending(void) { return false; } #endif /* !CONFIG_PM_SLEEP */ diff --git a/kernel/power/main.c b/kernel/power/main.c index 701853042c28..b5405af48ddb 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -17,10 +17,20 @@ DEFINE_MUTEX(pm_mutex); +#ifdef CONFIG_PM_SLEEP + unsigned int pm_flags; EXPORT_SYMBOL(pm_flags); -#ifdef CONFIG_PM_SLEEP +bool pm_apm_enabled(void) +{ + return !!(pm_flags & PM_APM); +} + +void pm_set_acpi_flag(void) +{ + pm_flags |= PM_ACPI; +} /* Routines for PM-transition notifications */ -- cgit v1.2.3 From aa33860158114d0df3c7997bc1dd41c0168e1c2a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 11 Feb 2011 00:06:54 +0100 Subject: PM: Remove CONFIG_PM_OPS After redefining CONFIG_PM to depend on (CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME) the CONFIG_PM_OPS option is redundant and can be replaced with CONFIG_PM. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 4 ++-- drivers/base/power/Makefile | 3 +-- drivers/net/e1000e/netdev.c | 8 ++++---- drivers/net/pch_gbe/pch_gbe_main.c | 2 +- drivers/pci/pci-driver.c | 4 ++-- drivers/scsi/Makefile | 2 +- drivers/scsi/scsi_priv.h | 2 +- drivers/scsi/scsi_sysfs.c | 2 +- drivers/usb/core/hcd-pci.c | 4 ++-- include/acpi/acpi_bus.h | 2 +- include/linux/pm.h | 2 +- kernel/power/Kconfig | 5 ----- 12 files changed, 17 insertions(+), 23 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index d6a8cd14de2e..8ea092fad3f6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -585,7 +585,7 @@ int acpi_suspend(u32 acpi_state) return -EINVAL; } -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM /** * acpi_pm_device_sleep_state - return preferred power state of ACPI device * in the system sleep state given by %acpi_target_sleep_state @@ -671,7 +671,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) *d_min_p = d_min; return d_max; } -#endif /* CONFIG_PM_OPS */ +#endif /* CONFIG_PM */ #ifdef CONFIG_PM_SLEEP /** diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index abe46edfe5b4..118c1b92a511 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile @@ -1,7 +1,6 @@ -obj-$(CONFIG_PM) += sysfs.o +obj-$(CONFIG_PM) += sysfs.o generic_ops.o obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o obj-$(CONFIG_PM_RUNTIME) += runtime.o -obj-$(CONFIG_PM_OPS) += generic_ops.o obj-$(CONFIG_PM_TRACE_RTC) += trace.o obj-$(CONFIG_PM_OPP) += opp.o diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2e5022849f18..6d513a383340 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5338,7 +5338,7 @@ void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) __e1000e_disable_aspm(pdev, state); } -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM static bool e1000e_pm_ready(struct e1000_adapter *adapter) { return !!adapter->tx_ring->buffer_info; @@ -5489,7 +5489,7 @@ static int e1000_runtime_resume(struct device *dev) return __e1000_resume(pdev); } #endif /* CONFIG_PM_RUNTIME */ -#endif /* CONFIG_PM_OPS */ +#endif /* CONFIG_PM */ static void e1000_shutdown(struct pci_dev *pdev) { @@ -6196,7 +6196,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { }; MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM static const struct dev_pm_ops e1000_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume) SET_RUNTIME_PM_OPS(e1000_runtime_suspend, @@ -6210,7 +6210,7 @@ static struct pci_driver e1000_driver = { .id_table = e1000_pci_tbl, .probe = e1000_probe, .remove = __devexit_p(e1000_remove), -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM .driver.pm = &e1000_pm_ops, #endif .shutdown = e1000_shutdown, diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index b99e90aca37d..8c66e22c3a0a 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -2446,7 +2446,7 @@ static struct pci_driver pch_gbe_pcidev = { .id_table = pch_gbe_pcidev_id, .probe = pch_gbe_probe, .remove = pch_gbe_remove, -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM .driver.pm = &pch_gbe_pm_ops, #endif .shutdown = pch_gbe_shutdown, diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 88246dd46452..d86ea8b01137 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -431,7 +431,7 @@ static void pci_device_shutdown(struct device *dev) pci_msix_shutdown(pci_dev); } -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM /* Auxiliary functions used for system resume and run-time resume. */ @@ -1059,7 +1059,7 @@ static int pci_pm_runtime_idle(struct device *dev) #endif /* !CONFIG_PM_RUNTIME */ -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM const struct dev_pm_ops pci_dev_pm_ops = { .prepare = pci_pm_prepare, diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2e9a87e8e7d8..ef6de669424b 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -165,7 +165,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o scsi_mod-y += scsi_trace.o -scsi_mod-$(CONFIG_PM_OPS) += scsi_pm.o +scsi_mod-$(CONFIG_PM) += scsi_pm.o scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index b4056d14f812..342ee1a9c41d 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -146,7 +146,7 @@ static inline void scsi_netlink_exit(void) {} #endif /* scsi_pm.c */ -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM extern const struct dev_pm_ops scsi_bus_pm_ops; #endif #ifdef CONFIG_PM_RUNTIME diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 490ce213204e..e44ff64233fd 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -383,7 +383,7 @@ struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, .uevent = scsi_bus_uevent, -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM .pm = &scsi_bus_pm_ops, #endif }; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index f71e8e307e0f..64a035ba2eab 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -335,7 +335,7 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM #ifdef CONFIG_PPC_PMAC static void powermac_set_asic(struct pci_dev *pci_dev, int enable) @@ -580,4 +580,4 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = { }; EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops); -#endif /* CONFIG_PM_OPS */ +#endif /* CONFIG_PM */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 78ca429929f7..ff103ba96b78 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -381,7 +381,7 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); int acpi_disable_wakeup_device_power(struct acpi_device *dev); -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM int acpi_pm_device_sleep_state(struct device *, int *); #else static inline int acpi_pm_device_sleep_state(struct device *d, int *p) diff --git a/include/linux/pm.h b/include/linux/pm.h index 21415cc91cbb..9279175a4557 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -267,7 +267,7 @@ const struct dev_pm_ops name = { \ * callbacks provided by device drivers supporting both the system sleep PM and * runtime PM, make the pm member point to generic_subsys_pm_ops. */ -#ifdef CONFIG_PM_OPS +#ifdef CONFIG_PM extern struct dev_pm_ops generic_subsys_pm_ops; #define GENERIC_SUBSYS_PM_OPS (&generic_subsys_pm_ops) #else diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 1e4d9238c5da..0710beead05b 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig @@ -220,11 +220,6 @@ config APM_EMULATION anything, try disabling/enabling this option (or disabling/enabling APM in your BIOS). -config PM_OPS - bool - depends on PM_SLEEP || PM_RUNTIME - default y - config ARCH_HAS_OPP bool -- cgit v1.2.3 From 6831c6edc7b272a08dd2a6c71bb183a48fe98ae6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 15 Feb 2011 21:22:24 +0100 Subject: PM: Drop pm_flags that is not necessary The variable pm_flags is used to prevent APM from being enabled along with ACPI, which would lead to problems. However, acpi_init() is always called before apm_init() and after acpi_init() has returned, it is known whether or not ACPI will be used. Namely, if acpi_disabled is not set after acpi_init() has returned, this means that ACPI is enabled. Thus, it is sufficient to check acpi_disabled in apm_init() to prevent APM from being enabled in parallel with ACPI. Signed-off-by: Rafael J. Wysocki Acked-by: Len Brown --- arch/x86/kernel/apm_32.c | 5 ++--- drivers/acpi/bus.c | 22 +++++----------------- include/linux/pm.h | 9 --------- include/linux/suspend.h | 6 ------ kernel/power/main.c | 13 ------------- 5 files changed, 7 insertions(+), 48 deletions(-) (limited to 'drivers/acpi') diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 0e4f24c2a746..15f47f741983 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -227,6 +227,7 @@ #include #include #include +#include #include #include @@ -2331,12 +2332,11 @@ static int __init apm_init(void) apm_info.disabled = 1; return -ENODEV; } - if (pm_flags & PM_ACPI) { + if (!acpi_disabled) { printk(KERN_NOTICE "apm: overridden by ACPI.\n"); apm_info.disabled = 1; return -ENODEV; } - pm_flags |= PM_APM; /* * Set up the long jump entry point to the APM BIOS, which is called @@ -2428,7 +2428,6 @@ static void __exit apm_exit(void) kthread_stop(kapmd_task); kapmd_task = NULL; } - pm_flags &= ~PM_APM; } module_init(apm_init); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 973b0709972c..9749980ca6ca 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1007,8 +1007,7 @@ struct kobject *acpi_kobj; static int __init acpi_init(void) { - int result = 0; - + int result; if (acpi_disabled) { printk(KERN_INFO PREFIX "Interpreter disabled.\n"); @@ -1023,29 +1022,18 @@ static int __init acpi_init(void) init_acpi_device_notify(); result = acpi_bus_init(); - - if (!result) { - pci_mmcfg_late_init(); - if (pm_apm_enabled()) { - printk(KERN_INFO PREFIX - "APM is already active, exiting\n"); - disable_acpi(); - result = -ENODEV; - } else { - pm_set_acpi_flag(); - } - } else + if (result) { disable_acpi(); - - if (acpi_disabled) return result; + } + pci_mmcfg_late_init(); acpi_scan_init(); acpi_ec_init(); acpi_debugfs_init(); acpi_sleep_proc_init(); acpi_wakeup_device_init(); - return result; + return 0; } subsys_initcall(acpi_init); diff --git a/include/linux/pm.h b/include/linux/pm.h index 9279175a4557..1f79c98f1e56 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -565,15 +565,6 @@ enum dpm_order { DPM_ORDER_DEV_LAST, }; -/* - * Global Power Management flags - * Used to keep APM and ACPI from both being active - */ -extern unsigned int pm_flags; - -#define PM_APM 1 -#define PM_ACPI 2 - extern int pm_generic_suspend(struct device *dev); extern int pm_generic_resume(struct device *dev); extern int pm_generic_freeze(struct device *dev); diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 5e364db8a56a..5a89e3612875 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -272,9 +272,6 @@ extern int unregister_pm_notifier(struct notifier_block *nb); register_pm_notifier(&fn##_nb); \ } -extern bool pm_apm_enabled(void); -extern void pm_set_acpi_flag(void); - /* drivers/base/power/wakeup.c */ extern bool events_check_enabled; @@ -295,9 +292,6 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) #define pm_notifier(fn, pri) do { (void)(fn); } while (0) -static inline bool pm_apm_enabled(void) { return false; } -static inline void pm_set_acpi_flag(void) {} - static inline bool pm_wakeup_pending(void) { return false; } #endif /* !CONFIG_PM_SLEEP */ diff --git a/kernel/power/main.c b/kernel/power/main.c index b5405af48ddb..8eaba5f27b10 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -19,19 +19,6 @@ DEFINE_MUTEX(pm_mutex); #ifdef CONFIG_PM_SLEEP -unsigned int pm_flags; -EXPORT_SYMBOL(pm_flags); - -bool pm_apm_enabled(void) -{ - return !!(pm_flags & PM_APM); -} - -void pm_set_acpi_flag(void) -{ - pm_flags |= PM_ACPI; -} - /* Routines for PM-transition notifications */ static BLOCKING_NOTIFIER_HEAD(pm_chain_head); -- cgit v1.2.3 From bb7ca747f8d6243b3943c5b133048652020f4a50 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 22 Mar 2011 16:30:21 -0700 Subject: backlight: add backlight type There may be multiple ways of controlling the backlight on a given machine. Allow drivers to expose the type of interface they are providing, making it possible for userspace to make appropriate policy decisions. Signed-off-by: Matthew Garrett Cc: Richard Purdie Cc: Chris Wilson Cc: David Airlie Cc: Alex Deucher Cc: Ben Skeggs Cc: Zhang Rui Cc: Len Brown Cc: Jesse Barnes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/stable/sysfs-class-backlight | 20 ++++++++++++++++++ drivers/acpi/video.c | 1 + drivers/gpu/drm/nouveau/nouveau_backlight.c | 2 ++ drivers/hid/hid-picolcd.c | 1 + drivers/macintosh/via-pmu-backlight.c | 1 + drivers/platform/x86/acer-wmi.c | 1 + drivers/platform/x86/asus-laptop.c | 1 + drivers/platform/x86/asus_acpi.c | 1 + drivers/platform/x86/classmate-laptop.c | 1 + drivers/platform/x86/compal-laptop.c | 1 + drivers/platform/x86/dell-laptop.c | 1 + drivers/platform/x86/eeepc-laptop.c | 1 + drivers/platform/x86/fujitsu-laptop.c | 1 + drivers/platform/x86/msi-laptop.c | 1 + drivers/platform/x86/msi-wmi.c | 1 + drivers/platform/x86/panasonic-laptop.c | 1 + drivers/platform/x86/sony-laptop.c | 3 ++- drivers/platform/x86/thinkpad_acpi.c | 1 + drivers/platform/x86/toshiba_acpi.c | 1 + drivers/staging/olpc_dcon/olpc_dcon.c | 1 + drivers/staging/samsung-laptop/samsung-laptop.c | 1 + drivers/usb/misc/appledisplay.c | 1 + drivers/video/atmel_lcdfb.c | 1 + drivers/video/aty/aty128fb.c | 1 + drivers/video/aty/atyfb_base.c | 1 + drivers/video/aty/radeon_backlight.c | 1 + drivers/video/backlight/88pm860x_bl.c | 1 + drivers/video/backlight/adp5520_bl.c | 1 + drivers/video/backlight/adp8860_bl.c | 1 + drivers/video/backlight/adx_bl.c | 1 + drivers/video/backlight/atmel-pwm-bl.c | 1 + drivers/video/backlight/backlight.c | 24 +++++++++++++++++++++- drivers/video/backlight/corgi_lcd.c | 1 + drivers/video/backlight/cr_bllcd.c | 1 + drivers/video/backlight/da903x_bl.c | 1 + drivers/video/backlight/ep93xx_bl.c | 1 + drivers/video/backlight/generic_bl.c | 1 + drivers/video/backlight/hp680_bl.c | 1 + drivers/video/backlight/jornada720_bl.c | 1 + drivers/video/backlight/kb3886_bl.c | 1 + drivers/video/backlight/locomolcd.c | 1 + drivers/video/backlight/max8925_bl.c | 1 + drivers/video/backlight/mbp_nvidia_bl.c | 1 + drivers/video/backlight/omap1_bl.c | 1 + drivers/video/backlight/pcf50633-backlight.c | 1 + drivers/video/backlight/progear_bl.c | 1 + drivers/video/backlight/pwm_bl.c | 1 + drivers/video/backlight/s6e63m0.c | 1 + drivers/video/backlight/tosa_bl.c | 1 + drivers/video/backlight/wm831x_bl.c | 1 + drivers/video/bf54x-lq043fb.c | 1 + drivers/video/bfin-t350mcqb-fb.c | 1 + drivers/video/imxfb.c | 1 + drivers/video/nvidia/nv_backlight.c | 1 + drivers/video/omap2/displays/panel-acx565akm.c | 1 + .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 1 + drivers/video/omap2/displays/panel-taal.c | 2 ++ drivers/video/riva/fbdev.c | 1 + include/linux/backlight.h | 9 ++++++++ 59 files changed, 111 insertions(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/Documentation/ABI/stable/sysfs-class-backlight b/Documentation/ABI/stable/sysfs-class-backlight index 4d637e1c4ff7..70302f370e7e 100644 --- a/Documentation/ABI/stable/sysfs-class-backlight +++ b/Documentation/ABI/stable/sysfs-class-backlight @@ -34,3 +34,23 @@ Contact: Richard Purdie Description: Maximum brightness for . Users: HAL + +What: /sys/class/backlight//type +Date: September 2010 +KernelVersion: 2.6.37 +Contact: Matthew Garrett +Description: + The type of interface controlled by . + "firmware": The driver uses a standard firmware interface + "platform": The driver uses a platform-specific interface + "raw": The driver controls hardware registers directly + + In the general case, when multiple backlight + interfaces are available for a single device, firmware + control should be preferred to platform control should + be preferred to raw control. Using a firmware + interface reduces the probability of confusion with + the hardware and the OS independently updating the + backlight state. Platform interfaces are mostly a + holdover from pre-standardisation of firmware + interfaces. diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 90f8f7676d1f..a9eec8c95a1f 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -795,6 +795,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) count++; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_FIRMWARE; props.max_brightness = device->brightness->count - 3; device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops, diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index d3a9c6e02477..18d7bcc54ce0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -98,6 +98,7 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev) return 0; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 31; bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev, &nv40_bl_ops, &props); @@ -121,6 +122,7 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev) return 0; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 1025; bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev, &nv50_bl_ops, &props); diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index de9cf21b3494..657da5a3d5c6 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c @@ -944,6 +944,7 @@ static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report * } memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; bdev = backlight_device_register(dev_name(dev), dev, data, &picolcd_blops, &props); diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c index ade1e656bfb2..b1d91170ded0 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c @@ -163,6 +163,7 @@ void __init pmu_backlight_init() snprintf(name, sizeof(name), "pmubl"); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data, &props); diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index ad3d099bf5c1..c9784705f6ac 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1031,6 +1031,7 @@ static int __devinit acer_backlight_init(struct device *dev) struct backlight_device *bd; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = max_brightness; bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops, &props); diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index f3aa6a7fdab6..5a6f7d7575d6 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -667,6 +667,7 @@ static int asus_backlight_init(struct asus_laptop *asus) memset(&props, 0, sizeof(struct backlight_properties)); props.max_brightness = 15; + props.type = BACKLIGHT_PLATFORM; bd = backlight_device_register(ASUS_LAPTOP_FILE, &asus->platform_device->dev, asus, diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index fe495939c307..f503607c0645 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -1507,6 +1507,7 @@ static int __init asus_acpi_init(void) } memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = 15; asus_backlight_device = backlight_device_register("asus", NULL, NULL, &asus_backlight_data, diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 911135425224..94f93b621d7b 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -564,6 +564,7 @@ static int cmpc_ipml_add(struct acpi_device *acpi) return -ENOMEM; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = 7; ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev, acpi->handle, &cmpc_bl_ops, diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c index 034572b980c9..eb95878fa583 100644 --- a/drivers/platform/x86/compal-laptop.c +++ b/drivers/platform/x86/compal-laptop.c @@ -970,6 +970,7 @@ static int __init compal_init(void) if (!acpi_video_backlight_support()) { struct backlight_properties props; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = BACKLIGHT_LEVEL_MAX; compalbl_device = backlight_device_register(DRIVER_NAME, NULL, NULL, diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index ad24ef36f9f7..de301aa8e5c3 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -671,6 +671,7 @@ static int __init dell_init(void) if (max_intensity) { struct backlight_properties props; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = max_intensity; dell_backlight_device = backlight_device_register("dell_backlight", &platform_device->dev, diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 49d9ad708f89..6605beac0d0e 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1147,6 +1147,7 @@ static int eeepc_backlight_init(struct eeepc_laptop *eeepc) struct backlight_device *bd; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = 15; bd = backlight_device_register(EEEPC_LAPTOP_FILE, &eeepc->platform_device->dev, eeepc, diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 95e3b0948e9c..493054c2dbe1 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -1128,6 +1128,7 @@ static int __init fujitsu_init(void) memset(&props, 0, sizeof(struct backlight_properties)); max_brightness = fujitsu->max_brightness; + props.type = BACKLIGHT_PLATFORM; props.max_brightness = max_brightness - 1; fujitsu->bl_device = backlight_device_register("fujitsu-laptop", NULL, NULL, diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index 7e9bb6df9d39..142d38579314 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -804,6 +804,7 @@ static int __init msi_init(void) } else { struct backlight_properties props; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = MSI_LCD_LEVEL_MAX - 1; msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL, &msibl_ops, diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 35278ad7e628..d5419c9ec07a 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -254,6 +254,7 @@ static int __init msi_wmi_init(void) if (!acpi_video_backlight_support()) { struct backlight_properties props; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = ARRAY_SIZE(backlight_map) - 1; backlight = backlight_device_register(DRV_NAME, NULL, NULL, &msi_backlight_ops, diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index cc1e0ba104d7..05be30ee158b 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -602,6 +602,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) } /* initialize backlight */ memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT]; pcc->backlight = backlight_device_register("panasonic", NULL, pcc, &pcc_backlight_ops, &props); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5e83370b0812..13d8d63bcca9 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1305,8 +1305,9 @@ static int sony_nc_add(struct acpi_device *device) "controlled by ACPI video driver\n"); } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) { - struct backlight_properties props; + struct backlight_properties props; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = SONY_MAX_BRIGHTNESS - 1; sony_backlight_device = backlight_device_register("sony", NULL, NULL, diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index eb9922385ef8..947bdcaa0ce9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6307,6 +6307,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) return 1; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = bright_maxlvl; props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME, diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 209cced786c6..63f42a22e102 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1018,6 +1018,7 @@ static int __init toshiba_acpi_init(void) create_toshiba_proc_entries(); } + props.type = BACKLIGHT_PLATFORM; props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; toshiba_backlight_device = backlight_device_register("toshiba", &toshiba_acpi.p_dev->dev, diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index b90c2cf3e247..750fe5045efa 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -574,6 +574,7 @@ static const struct backlight_ops dcon_bl_ops = { static struct backlight_properties dcon_bl_props = { .max_brightness = 15, + .type = BACKLIGHT_RAW, .power = FB_BLANK_UNBLANK, }; diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c index 6607a89ccb4b..25294462b8b6 100644 --- a/drivers/staging/samsung-laptop/samsung-laptop.c +++ b/drivers/staging/samsung-laptop/samsung-laptop.c @@ -781,6 +781,7 @@ static int __init samsung_init(void) /* create a backlight device to talk to this one */ memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = sabi_config->max_brightness; backlight_device = backlight_device_register("samsung", &sdev->dev, NULL, &backlight_ops, diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 1fa6ce3e4a23..68ab460a735c 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -282,6 +282,7 @@ static int appledisplay_probe(struct usb_interface *iface, snprintf(bl_name, sizeof(bl_name), "appledisplay%d", atomic_inc_return(&count_displays) - 1); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; pdata->bd = backlight_device_register(bl_name, NULL, pdata, &appledisplay_bl_data, &props); diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index bac163450216..4b4e8dadd6b2 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -127,6 +127,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo) return; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo, &atmel_lcdc_bl_ops, &props); diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 4cb6a576c567..b0b2ac335347 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1818,6 +1818,7 @@ static void aty128_bl_init(struct aty128fb_par *par) snprintf(name, sizeof(name), "aty128bl%d", info->node); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd = backlight_device_register(name, info->dev, par, &aty128_bl_data, &props); diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 94e293fce1d2..d437b3daf1f5 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2241,6 +2241,7 @@ static void aty_bl_init(struct atyfb_par *par) snprintf(name, sizeof(name), "atybl%d", info->node); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd = backlight_device_register(name, info->dev, par, &aty_bl_data, &props); diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index 9b811ddbce83..db572df7e1ef 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c @@ -158,6 +158,7 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo) snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd = backlight_device_register(name, rinfo->info->dev, pdata, &radeon_bl_data, &props); diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index b224396b86d5..e59623a15f3f 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -227,6 +227,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) } memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; bl = backlight_device_register(name, &pdev->dev, data, &pm860x_backlight_ops, &props); diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index 9f436e014f85..af3119707dbf 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c @@ -303,6 +303,7 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev) mutex_init(&data->lock); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = ADP5020_MAX_BRIGHTNESS; bl = backlight_device_register(pdev->name, data->master, data, &adp5520_bl_ops, &props); diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 734c650a47c4..d2a96a421ffd 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -709,6 +709,7 @@ static int __devinit adp8860_probe(struct i2c_client *client, i2c_set_clientdata(client, data); memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; props.max_brightness = ADP8860_MAX_BRIGHTNESS; mutex_init(&data->lock); diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c index fe9af129c5dd..c861c41af442 100644 --- a/drivers/video/backlight/adx_bl.c +++ b/drivers/video/backlight/adx_bl.c @@ -104,6 +104,7 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev) } memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 0xff; bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, bl, &adx_backlight_ops, &props); diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index e6a66dab088c..0443a4f71858 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -168,6 +168,7 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev) } memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min; bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl, &atmel_pwm_bl_ops, &props); diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 08703299ef61..80d292fb92d8 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -19,6 +19,12 @@ #include #endif +static const char const *backlight_types[] = { + [BACKLIGHT_RAW] = "raw", + [BACKLIGHT_PLATFORM] = "platform", + [BACKLIGHT_FIRMWARE] = "firmware", +}; + #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) /* This callback gets called when something important happens inside a @@ -169,6 +175,14 @@ static ssize_t backlight_store_brightness(struct device *dev, return rc; } +static ssize_t backlight_show_type(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + + return sprintf(buf, "%s\n", backlight_types[bd->props.type]); +} + static ssize_t backlight_show_max_brightness(struct device *dev, struct device_attribute *attr, char *buf) { @@ -234,6 +248,7 @@ static struct device_attribute bl_device_attributes[] = { __ATTR(actual_brightness, 0444, backlight_show_actual_brightness, NULL), __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), + __ATTR(type, 0444, backlight_show_type, NULL), __ATTR_NULL, }; @@ -292,9 +307,16 @@ struct backlight_device *backlight_device_register(const char *name, dev_set_drvdata(&new_bd->dev, devdata); /* Set default properties */ - if (props) + if (props) { memcpy(&new_bd->props, props, sizeof(struct backlight_properties)); + if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) { + WARN(1, "%s: invalid backlight type", name); + new_bd->props.type = BACKLIGHT_RAW; + } + } else { + new_bd->props.type = BACKLIGHT_RAW; + } rc = device_register(&new_bd->dev); if (rc) { diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index 1e71c35083bb..af6098396fe6 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -562,6 +562,7 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi) lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = pdata->max_intensity; lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd, &corgi_bl_ops, &props); diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c index 397d15eb1ea8..6c8c54041fae 100644 --- a/drivers/video/backlight/cr_bllcd.c +++ b/drivers/video/backlight/cr_bllcd.c @@ -193,6 +193,7 @@ static int cr_backlight_probe(struct platform_device *pdev) } memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL, &cr_backlight_ops, &props); if (IS_ERR(bdp)) { diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 87659ed79bd7..62043f12a5a4 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -136,6 +136,7 @@ static int da903x_backlight_probe(struct platform_device *pdev) da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2, DA9034_WLED_ISET(pdata->output_current)); + props.type = BACKLIGHT_RAW; props.max_brightness = max_brightness; bl = backlight_device_register(pdev->name, data->da903x_dev, data, &da903x_backlight_ops, &props); diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c index b0cc49184803..9f1e389d51d2 100644 --- a/drivers/video/backlight/ep93xx_bl.c +++ b/drivers/video/backlight/ep93xx_bl.c @@ -87,6 +87,7 @@ static int __init ep93xxbl_probe(struct platform_device *dev) ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = EP93XX_MAX_BRIGHT; bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl, &ep93xxbl_ops, &props); diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index 312ca619735d..8c6befd65a33 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c @@ -91,6 +91,7 @@ static int genericbl_probe(struct platform_device *pdev) name = machinfo->name; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = machinfo->max_intensity; bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops, &props); diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index 267d23f8d645..38aa00272141 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -109,6 +109,7 @@ static int __devinit hp680bl_probe(struct platform_device *pdev) struct backlight_device *bd; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = HP680_MAX_INTENSITY; bd = backlight_device_register("hp680-bl", &pdev->dev, NULL, &hp680bl_ops, &props); diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index 2f177b3a4885..40e4fa8fcf92 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c @@ -106,6 +106,7 @@ static int jornada_bl_probe(struct platform_device *pdev) struct backlight_device *bd; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = BL_MAX_BRIGHT; bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL, &jornada_bl_ops, &props); diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index f439a8632287..72dd5556a35b 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c @@ -149,6 +149,7 @@ static int kb3886bl_probe(struct platform_device *pdev) machinfo->limit_mask = -1; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = machinfo->max_intensity; kb3886_backlight_device = backlight_device_register("kb3886-bl", &pdev->dev, NULL, diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index d2f59015d517..bbca3127071e 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -184,6 +184,7 @@ static int locomolcd_probe(struct locomo_dev *ldev) local_irq_restore(flags); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 4; locomolcd_bl_device = backlight_device_register("locomo-bl", &ldev->dev, NULL, diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index 209acc105cbc..07e8e273ced0 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c @@ -136,6 +136,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev) data->current_brightness = 0; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = MAX_BRIGHTNESS; bl = backlight_device_register(name, &pdev->dev, data, &max8925_backlight_ops, &props); diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c index 1485f7345f49..74c33944aa86 100644 --- a/drivers/video/backlight/mbp_nvidia_bl.c +++ b/drivers/video/backlight/mbp_nvidia_bl.c @@ -367,6 +367,7 @@ static int __init mbp_init(void) return -ENXIO; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; props.max_brightness = 15; mbp_backlight_device = backlight_device_register("mbp_backlight", NULL, NULL, diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index d3bc56296c8d..08d26a72394c 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -146,6 +146,7 @@ static int omapbl_probe(struct platform_device *pdev) return -ENOMEM; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = OMAPBL_MAX_INTENSITY; dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops, &props); diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c index 3c424f7efdcc..ef5628d60563 100644 --- a/drivers/video/backlight/pcf50633-backlight.c +++ b/drivers/video/backlight/pcf50633-backlight.c @@ -112,6 +112,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev) if (!pcf_bl) return -ENOMEM; + bl_props.type = BACKLIGHT_RAW; bl_props.max_brightness = 0x3f; bl_props.power = FB_BLANK_UNBLANK; diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c index 809278c90738..6af183d6465e 100644 --- a/drivers/video/backlight/progear_bl.c +++ b/drivers/video/backlight/progear_bl.c @@ -84,6 +84,7 @@ static int progearbl_probe(struct platform_device *pdev) pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; progear_backlight_device = backlight_device_register("progear-bl", &pdev->dev, NULL, diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index 21866ec69656..2c2a2c703c14 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -108,6 +108,7 @@ static int pwm_backlight_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "got pwm for backlight\n"); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = data->max_brightness; bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb, &pwm_backlight_ops, &props); diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 5927db0da999..322040f686c2 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c @@ -778,6 +778,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi) bd->props.max_brightness = MAX_BRIGHTNESS; bd->props.brightness = MAX_BRIGHTNESS; + bd->props.type = BACKLIGHT_RAW; lcd->bd = bd; /* diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index 2a04b382ec48..425a7365470b 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c @@ -102,6 +102,7 @@ static int __devinit tosa_bl_probe(struct i2c_client *client, data->i2c = client; memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 512 - 1; data->bl = backlight_device_register("tosa-bl", &client->dev, data, &bl_ops, &props); diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c index 08fd87f3aecc..d4c6eb248ff9 100644 --- a/drivers/video/backlight/wm831x_bl.c +++ b/drivers/video/backlight/wm831x_bl.c @@ -193,6 +193,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev) data->current_brightness = 0; data->isink_reg = isink_reg; + props.type = BACKLIGHT_RAW; props.max_brightness = max_isel; bl = backlight_device_register("wm831x", &pdev->dev, data, &wm831x_backlight_ops, &props); diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index e7d0f525041e..2464b910b590 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -649,6 +649,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev) } #ifndef NO_BL_SUPPORT memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 255; bl_dev = backlight_device_register("bf54x-bl", NULL, NULL, &bfin_lq043fb_bl_ops, &props); diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 3cf77676947c..d8de29f0dd8d 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -545,6 +545,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) } #ifndef NO_BL_SUPPORT memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = 255; bl_dev = backlight_device_register("bf52x-bl", NULL, NULL, &bfin_lq043fb_bl_ops, &props); diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 69bd4a581d4a..ef72cb483834 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -499,6 +499,7 @@ static void imxfb_init_backlight(struct imxfb_info *fbi) memset(&props, 0, sizeof(struct backlight_properties)); props.max_brightness = 0xff; + props.type = BACKLIGHT_RAW; writel(fbi->pwmr, fbi->regs + LCDC_PWMR); bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi, diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c index 6aac6d1b937b..8471008aa6ff 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c @@ -111,6 +111,7 @@ void nvidia_bl_init(struct nvidia_par *par) snprintf(name, sizeof(name), "nvidiabl%d", info->node); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops, &props); diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c index e77310653207..7e04c921aa2a 100644 --- a/drivers/video/omap2/displays/panel-acx565akm.c +++ b/drivers/video/omap2/displays/panel-acx565akm.c @@ -534,6 +534,7 @@ static int acx_panel_probe(struct omap_dss_device *dssdev) props.fb_blank = FB_BLANK_UNBLANK; props.power = FB_BLANK_UNBLANK; + props.type = BACKLIGHT_RAW; bldev = backlight_device_register("acx565akm", &md->spi->dev, md, &acx565akm_bl_ops, &props); diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c index 9a138f650e05..d2b35d2df2a6 100644 --- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c @@ -99,6 +99,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) memset(&props, 0, sizeof(struct backlight_properties)); props.max_brightness = dssdev->max_backlight_level; + props.type = BACKLIGHT_RAW; bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev, &sharp_ls_bl_ops, &props); diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 61026f96ad20..c74e8b778ba1 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -729,6 +729,8 @@ static int taal_probe(struct omap_dss_device *dssdev) props.max_brightness = 255; else props.max_brightness = 127; + + props.type = BACKLIGHT_RAW; bldev = backlight_device_register("taal", &dssdev->dev, dssdev, &taal_bl_ops, &props); if (IS_ERR(bldev)) { diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index da388186d617..d8ab7be4fd6b 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -355,6 +355,7 @@ static void riva_bl_init(struct riva_par *par) snprintf(name, sizeof(name), "rivabl%d", info->node); memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_RAW; props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd = backlight_device_register(name, info->dev, par, &riva_bl_ops, &props); diff --git a/include/linux/backlight.h b/include/linux/backlight.h index 4a3d52e545e1..5ffc6dda4675 100644 --- a/include/linux/backlight.h +++ b/include/linux/backlight.h @@ -32,6 +32,13 @@ enum backlight_update_reason { BACKLIGHT_UPDATE_SYSFS, }; +enum backlight_type { + BACKLIGHT_RAW = 1, + BACKLIGHT_PLATFORM, + BACKLIGHT_FIRMWARE, + BACKLIGHT_TYPE_MAX, +}; + struct backlight_device; struct fb_info; @@ -62,6 +69,8 @@ struct backlight_properties { /* FB Blanking active? (values as for power) */ /* Due to be removed, please use (state & BL_CORE_FBBLANK) */ int fb_blank; + /* Backlight type */ + enum backlight_type type; /* Flags used to signal drivers of state changes */ /* Upper 4 bits are reserved for driver internal use */ unsigned int state; -- cgit v1.2.3 From 9661e92c10a9775243c1ecb73373528ed8725a10 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 22 Mar 2011 16:30:25 -0700 Subject: acpi: tie ACPI backlight devices to PCI devices if possible Dual-GPU machines may provide more than one ACPI backlight interface. Tie the backlight device to the GPU in order to allow userspace to identify the correct interface. Signed-off-by: Matthew Garrett Cc: Richard Purdie Cc: Chris Wilson Cc: David Airlie Cc: Alex Deucher Cc: Ben Skeggs Cc: Zhang Rui Cc: Len Brown Cc: Jesse Barnes Tested-by: Sedat Dilek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/video.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a9eec8c95a1f..a18e497f1c3c 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -782,6 +782,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (acpi_video_backlight_support()) { struct backlight_properties props; + struct pci_dev *pdev; + acpi_handle acpi_parent; + struct device *parent = NULL; int result; static int count = 0; char *name; @@ -794,10 +797,20 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) return; count++; + acpi_get_parent(device->dev->handle, &acpi_parent); + + pdev = acpi_get_pci_dev(acpi_parent); + if (pdev) { + parent = &pdev->dev; + pci_dev_put(pdev); + } + memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_FIRMWARE; props.max_brightness = device->brightness->count - 3; - device->backlight = backlight_device_register(name, NULL, device, + device->backlight = backlight_device_register(name, + parent, + device, &acpi_backlight_ops, &props); kfree(name); -- cgit v1.2.3