From e53e7fadc28a10683777bcc66c36aa76c1d3a21b Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Wed, 16 Mar 2011 23:13:54 -0500 Subject: [PATCH 01/99] fix sparc build-id conflicts due to debug and /boot images having the same build id --- kernel.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 43e9a3a2d..099a485ac 100644 --- a/kernel.spec +++ b/kernel.spec @@ -345,7 +345,7 @@ Summary: The Linux kernel %define asmarch sparc %define all_arch_configs kernel-%{version}-sparc64*.config %define make_target image -%define kernel_image arch/sparc/boot/image +%define kernel_image vmlinux %define image_install_path boot %define with_perf 0 %endif @@ -1972,6 +1972,10 @@ fi # and build. %changelog +* Wed Mar 16 2011 Dennis Gilmore +- build sparc imagae as vmlinux +- fixes buildid conflicts since the sparc kernel is just a elf image + * Tue Mar 15 2011 Chuck Ebbert 2.6.38-1 - Linux 2.6.38 From 93c9d729181afc03cccd8e807cc6a7fefbf88b69 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 17 Mar 2011 10:24:49 -0400 Subject: [PATCH 02/99] drop efi_default_physical.patch - it's actually setting up something that's neither physical nor virtual, and it's probably breaking EFI boots --- efi_default_physical.patch | 403 ------------------------------------- kernel.spec | 8 +- 2 files changed, 5 insertions(+), 406 deletions(-) delete mode 100644 efi_default_physical.patch diff --git a/efi_default_physical.patch b/efi_default_physical.patch deleted file mode 100644 index 41de7809e..000000000 --- a/efi_default_physical.patch +++ /dev/null @@ -1,403 +0,0 @@ -Default EFI to physical rather than virtual. Upstream seem to be going -in this direction. - -diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h -index 8e4a165..3c62f15 100644 ---- a/arch/x86/include/asm/efi.h -+++ b/arch/x86/include/asm/efi.h -@@ -93,6 +93,9 @@ extern int add_efi_memmap; - extern void efi_memblock_x86_reserve_range(void); - extern void efi_call_phys_prelog(void); - extern void efi_call_phys_epilog(void); -+extern void efi_call_phys_prelog_in_physmode(void); -+extern void efi_call_phys_epilog_in_physmode(void); -+extern void efi_pagetable_init(void); - - #ifndef CONFIG_EFI - /* -diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c -index 0fe27d7..e1158b0 100644 ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -58,6 +58,7 @@ struct efi_memory_map memmap; - - static struct efi efi_phys __initdata; - static efi_system_table_t efi_systab __initdata; -+static efi_runtime_services_t phys_runtime; - - static int __init setup_noefi(char *arg) - { -@@ -172,7 +173,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map( - return status; - } - --static efi_status_t __init phys_efi_get_time(efi_time_t *tm, -+static efi_status_t __init phys_efi_get_time_early(efi_time_t *tm, - efi_time_cap_t *tc) - { - efi_status_t status; -@@ -183,6 +184,112 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm, - return status; - } - -+static efi_status_t phys_efi_get_time(efi_time_t *tm, -+ efi_time_cap_t *tc) -+{ -+ efi_status_t status; -+ -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys2((void*)phys_runtime.get_time, tm, tc); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static efi_status_t __init phys_efi_set_time(efi_time_t *tm) -+{ -+ efi_status_t status; -+ -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys1((void*)phys_runtime.set_time, tm); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static efi_status_t phys_efi_get_wakeup_time(efi_bool_t *enabled, -+ efi_bool_t *pending, -+ efi_time_t *tm) -+{ -+ efi_status_t status; -+ -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys3((void*)phys_runtime.get_wakeup_time, enabled, -+ pending, tm); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static efi_status_t phys_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) -+{ -+ efi_status_t status; -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys2((void*)phys_runtime.set_wakeup_time, enabled, -+ tm); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static efi_status_t phys_efi_get_variable(efi_char16_t *name, -+ efi_guid_t *vendor, -+ u32 *attr, -+ unsigned long *data_size, -+ void *data) -+{ -+ efi_status_t status; -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys5((void*)phys_runtime.get_variable, name, vendor, -+ attr, data_size, data); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static efi_status_t phys_efi_get_next_variable(unsigned long *name_size, -+ efi_char16_t *name, -+ efi_guid_t *vendor) -+{ -+ efi_status_t status; -+ -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys3((void*)phys_runtime.get_next_variable, -+ name_size, name, vendor); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static efi_status_t phys_efi_set_variable(efi_char16_t *name, -+ efi_guid_t *vendor, -+ unsigned long attr, -+ unsigned long data_size, -+ void *data) -+{ -+ efi_status_t status; -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys5((void*)phys_runtime.set_variable, name, -+ vendor, attr, data_size, data); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static efi_status_t phys_efi_get_next_high_mono_count(u32 *count) -+{ -+ efi_status_t status; -+ efi_call_phys_prelog_in_physmode(); -+ status = efi_call_phys1((void*)phys_runtime.get_next_high_mono_count, -+ count); -+ efi_call_phys_epilog_in_physmode(); -+ return status; -+} -+ -+static void phys_efi_reset_system(int reset_type, -+ efi_status_t status, -+ unsigned long data_size, -+ efi_char16_t *data) -+{ -+ efi_call_phys_prelog_in_physmode(); -+ efi_call_phys4((void*)phys_runtime.reset_system, reset_type, status, -+ data_size, data); -+ efi_call_phys_epilog_in_physmode(); -+} -+ - int efi_set_rtc_mmss(unsigned long nowtime) - { - int real_seconds, real_minutes; -@@ -435,7 +542,9 @@ void __init efi_init(void) - * Make efi_get_time can be called before entering - * virtual mode. - */ -- efi.get_time = phys_efi_get_time; -+ efi.get_time = phys_efi_get_time_early; -+ -+ memcpy(&phys_runtime, runtime, sizeof(efi_runtime_services_t)); - } else - printk(KERN_ERR "Could not map the EFI runtime service " - "table!\n"); -@@ -466,6 +575,14 @@ void __init efi_init(void) - #if EFI_DEBUG - print_efi_memmap(); - #endif -+ -+#ifndef CONFIG_X86_64 -+ /* -+ * Only x86_64 supports physical mode as of now. Use virtual mode -+ * forcibly. -+ */ -+ usevirtefi = 1; -+#endif - } - - static void __init runtime_code_page_mkexec(void) -@@ -579,6 +696,27 @@ void __init efi_enter_virtual_mode(void) - memmap.map = NULL; - } - -+void __init efi_setup_physical_mode(void) -+{ -+#ifdef CONFIG_X86_64 -+ efi_pagetable_init(); -+#endif -+ efi.get_time = phys_efi_get_time; -+ efi.set_time = phys_efi_set_time; -+ efi.get_wakeup_time = phys_efi_get_wakeup_time; -+ efi.set_wakeup_time = phys_efi_set_wakeup_time; -+ efi.get_variable = phys_efi_get_variable; -+ efi.get_next_variable = phys_efi_get_next_variable; -+ efi.set_variable = phys_efi_set_variable; -+ efi.get_next_high_mono_count = -+ phys_efi_get_next_high_mono_count; -+ efi.reset_system = phys_efi_reset_system; -+ efi.set_virtual_address_map = NULL; /* Not needed */ -+ -+ early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); -+ memmap.map = NULL; -+} -+ - /* - * Convenience functions to obtain memory types and attributes - */ -diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c -index 5cab48e..90767b1 100644 ---- a/arch/x86/platform/efi/efi_32.c -+++ b/arch/x86/platform/efi/efi_32.c -@@ -110,3 +110,7 @@ void efi_call_phys_epilog(void) - - local_irq_restore(efi_rt_eflags); - } -+ -+void efi_call_phys_prelog_in_physmode(void) { /* Not supported */ } -+void efi_call_phys_epilog_in_physmode(void) { /* Not supported */ } -+ -diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c -index ac0621a..ad19fe9 100644 ---- a/arch/x86/platform/efi/efi_64.c -+++ b/arch/x86/platform/efi/efi_64.c -@@ -39,7 +39,9 @@ - #include - - static pgd_t save_pgd __initdata; --static unsigned long efi_flags __initdata; -+static DEFINE_PER_CPU(unsigned long, efi_flags); -+static DEFINE_PER_CPU(unsigned long, save_cr3); -+static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; - - static void __init early_mapping_set_exec(unsigned long start, - unsigned long end, -@@ -80,7 +82,7 @@ void __init efi_call_phys_prelog(void) - unsigned long vaddress; - - early_runtime_code_mapping_set_exec(1); -- local_irq_save(efi_flags); -+ local_irq_save(get_cpu_var(efi_flags)); - vaddress = (unsigned long)__va(0x0UL); - save_pgd = *pgd_offset_k(0x0UL); - set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); -@@ -94,10 +96,23 @@ void __init efi_call_phys_epilog(void) - */ - set_pgd(pgd_offset_k(0x0UL), save_pgd); - __flush_tlb_all(); -- local_irq_restore(efi_flags); -+ local_irq_restore(get_cpu_var(efi_flags)); - early_runtime_code_mapping_set_exec(0); - } - -+void efi_call_phys_prelog_in_physmode(void) -+{ -+ local_irq_save(get_cpu_var(efi_flags)); -+ get_cpu_var(save_cr3)= read_cr3(); -+ write_cr3(virt_to_phys(efi_pgd)); -+} -+ -+void efi_call_phys_epilog_in_physmode(void) -+{ -+ write_cr3(get_cpu_var(save_cr3)); -+ local_irq_restore(get_cpu_var(efi_flags)); -+} -+ - void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, - u32 type) - { -@@ -112,3 +127,78 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, - - return (void __iomem *)__va(phys_addr); - } -+ -+static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) -+{ -+ if (pgd_none(*pgd)) { -+ pud_t *pud = (pud_t *)get_zeroed_page(GFP_ATOMIC); -+ set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud))); -+ if (pud != pud_offset(pgd, 0)) -+ printk(KERN_ERR "EFI PAGETABLE BUG #00! %p <-> %p\n", -+ pud, pud_offset(pgd, 0)); -+ } -+ return pud_offset(pgd, vaddr); -+} -+ -+static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) -+{ -+ if (pud_none(*pud)) { -+ pmd_t *pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); -+ set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd))); -+ if (pmd != pmd_offset(pud, 0)) -+ printk(KERN_ERR "EFI PAGETABLE BUG #01! %p <-> %p\n", -+ pmd, pmd_offset(pud, 0)); -+ } -+ return pmd_offset(pud, vaddr); -+} -+ -+static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr) -+{ -+ if (pmd_none(*pmd)) { -+ pte_t *pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); -+ set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte))); -+ if (pte != pte_offset_kernel(pmd, 0)) -+ printk(KERN_ERR "EFI PAGETABLE BUG #02!\n"); -+ } -+ return pte_offset_kernel(pmd, vaddr); -+} -+ -+void __init efi_pagetable_init(void) -+{ -+ efi_memory_desc_t *md; -+ unsigned long size; -+ u64 start_pfn, end_pfn, pfn, vaddr; -+ void *p; -+ pgd_t *pgd; -+ pud_t *pud; -+ pmd_t *pmd; -+ pte_t *pte; -+ -+ memset(efi_pgd, 0, sizeof(efi_pgd)); -+ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { -+ md = p; -+ if (!(md->type & EFI_RUNTIME_SERVICES_CODE) && -+ !(md->type & EFI_RUNTIME_SERVICES_DATA)) -+ continue; -+ -+ start_pfn = md->phys_addr >> PAGE_SHIFT; -+ size = md->num_pages << EFI_PAGE_SHIFT; -+ end_pfn = PFN_UP(md->phys_addr + size); -+ -+ for (pfn = start_pfn; pfn <= end_pfn; pfn++) { -+ vaddr = pfn << PAGE_SHIFT; -+ pgd = efi_pgd + pgd_index(vaddr); -+ pud = fill_pud(pgd, vaddr); -+ pmd = fill_pmd(pud, vaddr); -+ pte = fill_pte(pmd, vaddr); -+ if (md->type & EFI_RUNTIME_SERVICES_CODE) -+ set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); -+ else -+ set_pte(pte, pfn_pte(pfn, PAGE_KERNEL)); -+ } -+ } -+ pgd = efi_pgd + pgd_index(PAGE_OFFSET); -+ set_pgd(pgd, *pgd_offset_k(PAGE_OFFSET)); -+ pgd = efi_pgd + pgd_index(__START_KERNEL_map); -+ set_pgd(pgd, *pgd_offset_k(__START_KERNEL_map)); -+} -diff --git a/include/linux/efi.h b/include/linux/efi.h -index fb737bc..c4e310e 100644 ---- a/include/linux/efi.h -+++ b/include/linux/efi.h -@@ -290,6 +290,7 @@ extern void efi_map_pal_code (void); - extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); - extern void efi_gettimeofday (struct timespec *ts); - extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ -+extern void efi_setup_physical_mode(void); - extern u64 efi_get_iobase (void); - extern u32 efi_mem_type (unsigned long phys_addr); - extern u64 efi_mem_attributes (unsigned long phys_addr); -diff --git a/include/linux/init.h b/include/linux/init.h -index 577671c..2f1b28f 100644 ---- a/include/linux/init.h -+++ b/include/linux/init.h -@@ -149,6 +149,7 @@ extern int do_one_initcall(initcall_t fn); - extern char __initdata boot_command_line[]; - extern char *saved_command_line; - extern unsigned int reset_devices; -+extern unsigned int usevirtefi; - - /* used by init/main.c */ - void setup_arch(char **); -diff --git a/init/main.c b/init/main.c -index 8646401..726025e 100644 ---- a/init/main.c -+++ b/init/main.c -@@ -196,6 +196,14 @@ static int __init set_reset_devices(char *str) - - __setup("reset_devices", set_reset_devices); - -+unsigned int usevirtefi; -+static int __init set_virt_efi(char *str) -+{ -+ usevirtefi = 1; -+ return 1; -+} -+__setup("virtefi", set_virt_efi); -+ - static const char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; - const char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; - static const char *panic_later, *panic_param; -@@ -668,8 +676,12 @@ asmlinkage void __init start_kernel(void) - pidmap_init(); - anon_vma_init(); - #ifdef CONFIG_X86 -- if (efi_enabled) -- efi_enter_virtual_mode(); -+ if (efi_enabled) { -+ if (usevirtefi) -+ efi_enter_virtual_mode(); -+ else -+ efi_setup_physical_mode(); -+ } - #endif - thread_info_cache_init(); - cred_init(); diff --git a/kernel.spec b/kernel.spec index 099a485ac..25ae1f8ef 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -721,7 +721,6 @@ Patch12018: neuter_intel_microcode_load.patch Patch12101: apple_backlight.patch Patch12102: efifb_update.patch Patch12200: acpi_reboot.patch -Patch12210: efi_default_physical.patch # Runtime power management Patch12202: linux-2.6-ehci-check-port-status.patch @@ -1349,7 +1348,6 @@ ApplyPatch neuter_intel_microcode_load.patch ApplyPatch apple_backlight.patch ApplyPatch efifb_update.patch ApplyPatch acpi_reboot.patch -ApplyPatch efi_default_physical.patch # Runtime PM ApplyPatch linux-2.6-ehci-check-port-status.patch @@ -1972,6 +1970,10 @@ fi # and build. %changelog +* Thu Mar 17 2011 Matthew Garrett 2.6.38-2 +- drop efi_default_physical.patch - it's actually setting up something that's + neither physical nor virtual, and it's probably breaking EFI boots + * Wed Mar 16 2011 Dennis Gilmore - build sparc imagae as vmlinux - fixes buildid conflicts since the sparc kernel is just a elf image From c5e062a0ef22050354418eaef7a06849e7e64247 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 21 Mar 2011 20:00:10 -0400 Subject: [PATCH 03/99] Add contents of 2.6.38.1 patch queue --- add-appleir-usb-driver.patch | 4 +- config-generic | 1 + git-linus.diff | 2604 ++++++++++++++++++++++++++++++++++ kernel.spec | 7 +- 4 files changed, 2612 insertions(+), 4 deletions(-) diff --git a/add-appleir-usb-driver.patch b/add-appleir-usb-driver.patch index 61edb8061..af4f968f6 100644 --- a/add-appleir-usb-driver.patch +++ b/add-appleir-usb-driver.patch @@ -99,9 +99,9 @@ index baa25ad..abc5bd7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1244,8 +1244,6 @@ static const struct hid_device_id hid_blacklist[] = { - #if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE) + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, - #endif - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, diff --git a/config-generic b/config-generic index c07e5b85a..1a4649f08 100644 --- a/config-generic +++ b/config-generic @@ -3071,6 +3071,7 @@ CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m +CONFIG_HID_ACRUX=m CONFIG_HID_ACRUX_FF=m CONFIG_HID_EMS_FF=m CONFIG_HID_ELECOM=m diff --git a/git-linus.diff b/git-linus.diff index e69de29bb..4e0798a9e 100644 --- a/git-linus.diff +++ b/git-linus.diff @@ -0,0 +1,2604 @@ +--- vanilla-2.6.38.0.orig/fs/dcache.c ++++ vanilla-2.6.38.0/fs/dcache.c +@@ -296,8 +296,12 @@ static struct dentry *d_kill(struct dent + __releases(parent->d_lock) + __releases(dentry->d_inode->i_lock) + { +- dentry->d_parent = NULL; + list_del(&dentry->d_u.d_child); ++ /* ++ * Inform try_to_ascend() that we are no longer attached to the ++ * dentry tree ++ */ ++ dentry->d_flags |= DCACHE_DISCONNECTED; + if (parent) + spin_unlock(&parent->d_lock); + dentry_iput(dentry); +@@ -1012,6 +1016,35 @@ void shrink_dcache_for_umount(struct sup + } + + /* ++ * This tries to ascend one level of parenthood, but ++ * we can race with renaming, so we need to re-check ++ * the parenthood after dropping the lock and check ++ * that the sequence number still matches. ++ */ ++static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq) ++{ ++ struct dentry *new = old->d_parent; ++ ++ rcu_read_lock(); ++ spin_unlock(&old->d_lock); ++ spin_lock(&new->d_lock); ++ ++ /* ++ * might go back up the wrong parent if we have had a rename ++ * or deletion ++ */ ++ if (new != old->d_parent || ++ (old->d_flags & DCACHE_DISCONNECTED) || ++ (!locked && read_seqretry(&rename_lock, seq))) { ++ spin_unlock(&new->d_lock); ++ new = NULL; ++ } ++ rcu_read_unlock(); ++ return new; ++} ++ ++ ++/* + * Search for at least 1 mount point in the dentry's subdirs. + * We descend to the next level whenever the d_subdirs + * list is non-empty and continue searching. +@@ -1066,24 +1099,10 @@ resume: + * All done at this level ... ascend and resume the search. + */ + if (this_parent != parent) { +- struct dentry *tmp; +- struct dentry *child; +- +- tmp = this_parent->d_parent; +- rcu_read_lock(); +- spin_unlock(&this_parent->d_lock); +- child = this_parent; +- this_parent = tmp; +- spin_lock(&this_parent->d_lock); +- /* might go back up the wrong parent if we have had a rename +- * or deletion */ +- if (this_parent != child->d_parent || +- (!locked && read_seqretry(&rename_lock, seq))) { +- spin_unlock(&this_parent->d_lock); +- rcu_read_unlock(); ++ struct dentry *child = this_parent; ++ this_parent = try_to_ascend(this_parent, locked, seq); ++ if (!this_parent) + goto rename_retry; +- } +- rcu_read_unlock(); + next = child->d_u.d_child.next; + goto resume; + } +@@ -1181,24 +1200,10 @@ resume: + * All done at this level ... ascend and resume the search. + */ + if (this_parent != parent) { +- struct dentry *tmp; +- struct dentry *child; +- +- tmp = this_parent->d_parent; +- rcu_read_lock(); +- spin_unlock(&this_parent->d_lock); +- child = this_parent; +- this_parent = tmp; +- spin_lock(&this_parent->d_lock); +- /* might go back up the wrong parent if we have had a rename +- * or deletion */ +- if (this_parent != child->d_parent || +- (!locked && read_seqretry(&rename_lock, seq))) { +- spin_unlock(&this_parent->d_lock); +- rcu_read_unlock(); ++ struct dentry *child = this_parent; ++ this_parent = try_to_ascend(this_parent, locked, seq); ++ if (!this_parent) + goto rename_retry; +- } +- rcu_read_unlock(); + next = child->d_u.d_child.next; + goto resume; + } +@@ -2942,28 +2947,14 @@ resume: + spin_unlock(&dentry->d_lock); + } + if (this_parent != root) { +- struct dentry *tmp; +- struct dentry *child; +- +- tmp = this_parent->d_parent; ++ struct dentry *child = this_parent; + if (!(this_parent->d_flags & DCACHE_GENOCIDE)) { + this_parent->d_flags |= DCACHE_GENOCIDE; + this_parent->d_count--; + } +- rcu_read_lock(); +- spin_unlock(&this_parent->d_lock); +- child = this_parent; +- this_parent = tmp; +- spin_lock(&this_parent->d_lock); +- /* might go back up the wrong parent if we have had a rename +- * or deletion */ +- if (this_parent != child->d_parent || +- (!locked && read_seqretry(&rename_lock, seq))) { +- spin_unlock(&this_parent->d_lock); +- rcu_read_unlock(); ++ this_parent = try_to_ascend(this_parent, locked, seq); ++ if (!this_parent) + goto rename_retry; +- } +- rcu_read_unlock(); + next = child->d_u.d_child.next; + goto resume; + } +--- vanilla-2.6.38.0.orig/include/linux/ftrace.h ++++ vanilla-2.6.38.0/include/linux/ftrace.h +@@ -428,6 +428,7 @@ extern void unregister_ftrace_graph(void + + extern void ftrace_graph_init_task(struct task_struct *t); + extern void ftrace_graph_exit_task(struct task_struct *t); ++extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu); + + static inline int task_curr_ret_stack(struct task_struct *t) + { +@@ -451,6 +452,7 @@ static inline void unpause_graph_tracing + + static inline void ftrace_graph_init_task(struct task_struct *t) { } + static inline void ftrace_graph_exit_task(struct task_struct *t) { } ++static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { } + + static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc, + trace_func_graph_ent_t entryfunc) +--- vanilla-2.6.38.0.orig/kernel/sched.c ++++ vanilla-2.6.38.0/kernel/sched.c +@@ -5572,7 +5572,7 @@ void __cpuinit init_idle(struct task_str + * The idle tasks have their own, simple scheduling class: + */ + idle->sched_class = &idle_sched_class; +- ftrace_graph_init_task(idle); ++ ftrace_graph_init_idle_task(idle, cpu); + } + + /* +--- vanilla-2.6.38.0.orig/kernel/trace/ftrace.c ++++ vanilla-2.6.38.0/kernel/trace/ftrace.c +@@ -3328,7 +3328,7 @@ static int start_graph_tracing(void) + /* The cpu_boot init_task->ret_stack will never be freed */ + for_each_online_cpu(cpu) { + if (!idle_task(cpu)->ret_stack) +- ftrace_graph_init_task(idle_task(cpu)); ++ ftrace_graph_init_idle_task(idle_task(cpu), cpu); + } + + do { +@@ -3418,6 +3418,49 @@ void unregister_ftrace_graph(void) + mutex_unlock(&ftrace_lock); + } + ++static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); ++ ++static void ++graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) ++{ ++ atomic_set(&t->tracing_graph_pause, 0); ++ atomic_set(&t->trace_overrun, 0); ++ t->ftrace_timestamp = 0; ++ /* make curr_ret_stack visable before we add the ret_stack */ ++ smp_wmb(); ++ t->ret_stack = ret_stack; ++} ++ ++/* ++ * Allocate a return stack for the idle task. May be the first ++ * time through, or it may be done by CPU hotplug online. ++ */ ++void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) ++{ ++ t->curr_ret_stack = -1; ++ /* ++ * The idle task has no parent, it either has its own ++ * stack or no stack at all. ++ */ ++ if (t->ret_stack) ++ WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu)); ++ ++ if (ftrace_graph_active) { ++ struct ftrace_ret_stack *ret_stack; ++ ++ ret_stack = per_cpu(idle_ret_stack, cpu); ++ if (!ret_stack) { ++ ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH ++ * sizeof(struct ftrace_ret_stack), ++ GFP_KERNEL); ++ if (!ret_stack) ++ return; ++ per_cpu(idle_ret_stack, cpu) = ret_stack; ++ } ++ graph_init_task(t, ret_stack); ++ } ++} ++ + /* Allocate a return stack for newly created task */ + void ftrace_graph_init_task(struct task_struct *t) + { +@@ -3433,12 +3476,7 @@ void ftrace_graph_init_task(struct task_ + GFP_KERNEL); + if (!ret_stack) + return; +- atomic_set(&t->tracing_graph_pause, 0); +- atomic_set(&t->trace_overrun, 0); +- t->ftrace_timestamp = 0; +- /* make curr_ret_stack visable before we add the ret_stack */ +- smp_wmb(); +- t->ret_stack = ret_stack; ++ graph_init_task(t, ret_stack); + } + } + +--- vanilla-2.6.38.0.orig/arch/x86/kernel/e820.c ++++ vanilla-2.6.38.0/arch/x86/kernel/e820.c +@@ -847,15 +847,21 @@ static int __init parse_memopt(char *p) + if (!p) + return -EINVAL; + +-#ifdef CONFIG_X86_32 + if (!strcmp(p, "nopentium")) { ++#ifdef CONFIG_X86_32 + setup_clear_cpu_cap(X86_FEATURE_PSE); + return 0; +- } ++#else ++ printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n"); ++ return -EINVAL; + #endif ++ } + + userdef = 1; + mem_size = memparse(p, &p); ++ /* don't remove all of memory when handling "mem={invalid}" param */ ++ if (mem_size == 0) ++ return -EINVAL; + e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1); + + return 0; +--- vanilla-2.6.38.0.orig/drivers/ata/ahci.c ++++ vanilla-2.6.38.0/drivers/ata/ahci.c +@@ -260,6 +260,7 @@ static const struct pci_device_id ahci_p + { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ + { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ ++ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ + + /* JMicron 360/1/3/5/6, match class to avoid IDE function */ +@@ -383,6 +384,8 @@ static const struct pci_device_id ahci_p + .class = PCI_CLASS_STORAGE_SATA_AHCI, + .class_mask = 0xffffff, + .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ ++ { PCI_DEVICE(0x1b4b, 0x9125), ++ .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ + + /* Promise */ + { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ +--- vanilla-2.6.38.0.orig/drivers/ata/libata-eh.c ++++ vanilla-2.6.38.0/drivers/ata/libata-eh.c +@@ -1618,7 +1618,7 @@ static void ata_eh_analyze_serror(struct + * host links. For disabled PMP links, only N bit is + * considered as X bit is left at 1 for link plugging. + */ +- if (link->lpm_policy != ATA_LPM_MAX_POWER) ++ if (link->lpm_policy > ATA_LPM_MAX_POWER) + hotplug_mask = 0; /* hotplug doesn't work w/ LPM */ + else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link)) + hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG; +--- vanilla-2.6.38.0.orig/drivers/infiniband/core/cma.c ++++ vanilla-2.6.38.0/drivers/infiniband/core/cma.c +@@ -1210,6 +1210,11 @@ static int cma_req_handler(struct ib_cm_ + cm_id->context = conn_id; + cm_id->cm_handler = cma_ib_handler; + ++ /* ++ * Protect against the user destroying conn_id from another thread ++ * until we're done accessing it. ++ */ ++ atomic_inc(&conn_id->refcount); + ret = conn_id->id.event_handler(&conn_id->id, &event); + if (!ret) { + /* +@@ -1222,8 +1227,10 @@ static int cma_req_handler(struct ib_cm_ + ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); + mutex_unlock(&lock); + mutex_unlock(&conn_id->handler_mutex); ++ cma_deref_id(conn_id); + goto out; + } ++ cma_deref_id(conn_id); + + /* Destroy the CM ID by returning a non-zero value. */ + conn_id->cm_id.ib = NULL; +@@ -1425,17 +1432,25 @@ static int iw_conn_req_handler(struct iw + event.param.conn.private_data_len = iw_event->private_data_len; + event.param.conn.initiator_depth = attr.max_qp_init_rd_atom; + event.param.conn.responder_resources = attr.max_qp_rd_atom; ++ ++ /* ++ * Protect against the user destroying conn_id from another thread ++ * until we're done accessing it. ++ */ ++ atomic_inc(&conn_id->refcount); + ret = conn_id->id.event_handler(&conn_id->id, &event); + if (ret) { + /* User wants to destroy the CM ID */ + conn_id->cm_id.iw = NULL; + cma_exch(conn_id, CMA_DESTROYING); + mutex_unlock(&conn_id->handler_mutex); ++ cma_deref_id(conn_id); + rdma_destroy_id(&conn_id->id); + goto out; + } + + mutex_unlock(&conn_id->handler_mutex); ++ cma_deref_id(conn_id); + + out: + if (dev) +--- vanilla-2.6.38.0.orig/fs/partitions/osf.c ++++ vanilla-2.6.38.0/fs/partitions/osf.c +@@ -10,7 +10,7 @@ + #include "check.h" + #include "osf.h" + +-#define MAX_OSF_PARTITIONS 8 ++#define MAX_OSF_PARTITIONS 18 + + int osf_partition(struct parsed_partitions *state) + { +--- vanilla-2.6.38.0.orig/drivers/infiniband/core/cm.c ++++ vanilla-2.6.38.0/drivers/infiniband/core/cm.c +@@ -2989,6 +2989,7 @@ static int cm_sidr_req_handler(struct cm + goto out; /* No match. */ + } + atomic_inc(&cur_cm_id_priv->refcount); ++ atomic_inc(&cm_id_priv->refcount); + spin_unlock_irq(&cm.lock); + + cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler; +--- vanilla-2.6.38.0.orig/arch/x86/kernel/early-quirks.c ++++ vanilla-2.6.38.0/arch/x86/kernel/early-quirks.c +@@ -159,7 +159,12 @@ static void __init ati_bugs_contd(int nu + if (rev >= 0x40) + acpi_fix_pin2_polarity = 1; + +- if (rev > 0x13) ++ /* ++ * SB600: revisions 0x11, 0x12, 0x13, 0x14, ... ++ * SB700: revisions 0x39, 0x3a, ... ++ * SB800: revisions 0x40, 0x41, ... ++ */ ++ if (rev >= 0x39) + return; + + if (acpi_use_timer_override) +--- vanilla-2.6.38.0.orig/arch/microblaze/include/asm/uaccess.h ++++ vanilla-2.6.38.0/arch/microblaze/include/asm/uaccess.h +@@ -120,16 +120,16 @@ static inline unsigned long __must_check + { + /* normal memset with two words to __ex_table */ + __asm__ __volatile__ ( \ +- "1: sb r0, %2, r0;" \ ++ "1: sb r0, %1, r0;" \ + " addik %0, %0, -1;" \ + " bneid %0, 1b;" \ +- " addik %2, %2, 1;" \ ++ " addik %1, %1, 1;" \ + "2: " \ + __EX_TABLE_SECTION \ + ".word 1b,2b;" \ + ".previous;" \ +- : "=r"(n) \ +- : "0"(n), "r"(to) ++ : "=r"(n), "=r"(to) \ ++ : "0"(n), "1"(to) + ); + return n; + } +--- vanilla-2.6.38.0.orig/arch/x86/kernel/alternative.c ++++ vanilla-2.6.38.0/arch/x86/kernel/alternative.c +@@ -620,7 +620,12 @@ static int __kprobes stop_machine_text_p + flush_icache_range((unsigned long)p->addr, + (unsigned long)p->addr + p->len); + } +- ++ /* ++ * Intel Archiecture Software Developer's Manual section 7.1.3 specifies ++ * that a core serializing instruction such as "cpuid" should be ++ * executed on _each_ core before the new instruction is made visible. ++ */ ++ sync_core(); + return 0; + } + +--- vanilla-2.6.38.0.orig/security/tomoyo/file.c ++++ vanilla-2.6.38.0/security/tomoyo/file.c +@@ -927,7 +927,7 @@ int tomoyo_check_open_permission(struct + struct path *path, const int flag) + { + const u8 acc_mode = ACC_MODE(flag); +- int error = -ENOMEM; ++ int error = 0; + struct tomoyo_path_info buf; + struct tomoyo_request_info r; + int idx; +@@ -938,9 +938,6 @@ int tomoyo_check_open_permission(struct + buf.name = NULL; + r.mode = TOMOYO_CONFIG_DISABLED; + idx = tomoyo_read_lock(); +- if (!tomoyo_get_realpath(&buf, path)) +- goto out; +- error = 0; + /* + * If the filename is specified by "deny_rewrite" keyword, + * we need to check "allow_rewrite" permission when the filename is not +--- vanilla-2.6.38.0.orig/drivers/gpu/drm/i915/i915_irq.c ++++ vanilla-2.6.38.0/drivers/gpu/drm/i915/i915_irq.c +@@ -1377,7 +1377,12 @@ int i915_enable_vblank(struct drm_device + else + i915_enable_pipestat(dev_priv, pipe, + PIPE_VBLANK_INTERRUPT_ENABLE); ++ ++ /* maintain vblank delivery even in deep C-states */ ++ if (dev_priv->info->gen == 3) ++ I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); ++ + return 0; + } + +@@ -1390,6 +1395,10 @@ void i915_disable_vblank(struct drm_devi + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ++ if (dev_priv->info->gen == 3) ++ I915_WRITE(INSTPM, ++ INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS); ++ + if (HAS_PCH_SPLIT(dev)) + ironlake_disable_display_irq(dev_priv, (pipe == 0) ? + DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); +--- vanilla-2.6.38.0.orig/drivers/gpu/drm/i915/i915_reg.h ++++ vanilla-2.6.38.0/drivers/gpu/drm/i915/i915_reg.h +@@ -405,9 +405,12 @@ + #define I915_ERROR_INSTRUCTION (1<<0) + #define INSTPM 0x020c0 + #define INSTPM_SELF_EN (1<<12) /* 915GM only */ ++#define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts ++ will not assert AGPBUSY# and will only ++ be delivered when out of C3. */ + #define ACTHD 0x020c8 + #define FW_BLC 0x020d8 +-#define FW_BLC2 0x020dc ++#define FW_BLC2 0x020dc + #define FW_BLC_SELF 0x020e0 /* 915+ only */ + #define FW_BLC_SELF_EN_MASK (1<<31) + #define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */ +--- vanilla-2.6.38.0.orig/drivers/gpu/drm/radeon/atombios_crtc.c ++++ vanilla-2.6.38.0/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -61,8 +61,8 @@ static void atombios_overscan_setup(stru + args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); + args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); + } else if (a2 > a1) { +- args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); +- args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); ++ args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); ++ args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); + } + break; + case RMX_FULL: +--- vanilla-2.6.38.0.orig/drivers/gpu/drm/drm_sysfs.c ++++ vanilla-2.6.38.0/drivers/gpu/drm/drm_sysfs.c +@@ -158,8 +158,15 @@ static ssize_t status_show(struct device + { + struct drm_connector *connector = to_drm_connector(device); + enum drm_connector_status status; ++ int ret; ++ ++ ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex); ++ if (ret) ++ return ret; + + status = connector->funcs->detect(connector, true); ++ mutex_unlock(&connector->dev->mode_config.mutex); ++ + return snprintf(buf, PAGE_SIZE, "%s\n", + drm_get_connector_status_name(status)); + } +--- vanilla-2.6.38.0.orig/drivers/net/wireless/ath/ath9k/hw.c ++++ vanilla-2.6.38.0/drivers/net/wireless/ath/ath9k/hw.c +@@ -495,6 +495,17 @@ static int __ath9k_hw_init(struct ath_hw + if (ah->hw_version.devid == AR5416_AR9100_DEVID) + ah->hw_version.macVersion = AR_SREV_VERSION_9100; + ++ /* ++ * Read back AR_WA into a permanent copy and set bits 14 and 17. ++ * We need to do this to avoid RMW of this register. We cannot ++ * read the reg when chip is asleep. ++ */ ++ ah->WARegVal = REG_READ(ah, AR_WA); ++ ah->WARegVal |= (AR_WA_D3_L1_DISABLE | ++ AR_WA_ASPM_TIMER_BASED_DISABLE); ++ ++ ath9k_hw_read_revisions(ah); ++ + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { + ath_err(common, "Couldn't reset chip\n"); + return -EIO; +@@ -563,14 +574,6 @@ static int __ath9k_hw_init(struct ath_hw + + ath9k_hw_init_mode_regs(ah); + +- /* +- * Read back AR_WA into a permanent copy and set bits 14 and 17. +- * We need to do this to avoid RMW of this register. We cannot +- * read the reg when chip is asleep. +- */ +- ah->WARegVal = REG_READ(ah, AR_WA); +- ah->WARegVal |= (AR_WA_D3_L1_DISABLE | +- AR_WA_ASPM_TIMER_BASED_DISABLE); + + if (ah->is_pciexpress) + ath9k_hw_configpcipowersave(ah, 0, 0); +@@ -1082,8 +1085,6 @@ static bool ath9k_hw_set_reset_power_on( + return false; + } + +- ath9k_hw_read_revisions(ah); +- + return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); + } + +--- vanilla-2.6.38.0.orig/drivers/net/wireless/ath/ath9k/recv.c ++++ vanilla-2.6.38.0/drivers/net/wireless/ath/ath9k/recv.c +@@ -439,9 +439,7 @@ u32 ath_calcrxfilter(struct ath_softc *s + * mode interface or when in monitor mode. AP mode does not need this + * since it receives all in-BSS frames anyway. + */ +- if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && +- (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || +- (sc->sc_ah->is_monitoring)) ++ if (sc->sc_ah->is_monitoring) + rfilt |= ATH9K_RX_FILTER_PROM; + + if (sc->rx.rxfilter & FIF_CONTROL) +--- vanilla-2.6.38.0.orig/drivers/tty/serial/mrst_max3110.c ++++ vanilla-2.6.38.0/drivers/tty/serial/mrst_max3110.c +@@ -51,7 +51,7 @@ + struct uart_max3110 { + struct uart_port port; + struct spi_device *spi; +- char name[24]; ++ char name[SPI_NAME_SIZE]; + + wait_queue_head_t wq; + struct task_struct *main_thread; +--- vanilla-2.6.38.0.orig/drivers/tty/serial/8250.c ++++ vanilla-2.6.38.0/drivers/tty/serial/8250.c +@@ -954,6 +954,23 @@ static int broken_efr(struct uart_8250_p + return 0; + } + ++static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) ++{ ++ unsigned char status; ++ ++ status = serial_in(up, 0x04); /* EXCR2 */ ++#define PRESL(x) ((x) & 0x30) ++ if (PRESL(status) == 0x10) { ++ /* already in high speed mode */ ++ return 0; ++ } else { ++ status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ ++ status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ ++ serial_outp(up, 0x04, status); ++ } ++ return 1; ++} ++ + /* + * We know that the chip has FIFOs. Does it have an EFR? The + * EFR is located in the same register position as the IIR and +@@ -1025,12 +1042,8 @@ static void autoconfig_16550a(struct uar + quot = serial_dl_read(up); + quot <<= 3; + +- status1 = serial_in(up, 0x04); /* EXCR2 */ +- status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ +- status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ +- serial_outp(up, 0x04, status1); +- +- serial_dl_write(up, quot); ++ if (ns16550a_goto_highspeed(up)) ++ serial_dl_write(up, quot); + + serial_outp(up, UART_LCR, 0); + +@@ -3025,17 +3038,13 @@ void serial8250_resume_port(int line) + struct uart_8250_port *up = &serial8250_ports[line]; + + if (up->capabilities & UART_NATSEMI) { +- unsigned char tmp; +- + /* Ensure it's still in high speed mode */ + serial_outp(up, UART_LCR, 0xE0); + +- tmp = serial_in(up, 0x04); /* EXCR2 */ +- tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ +- tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ +- serial_outp(up, 0x04, tmp); ++ ns16550a_goto_highspeed(up); + + serial_outp(up, UART_LCR, 0); ++ up->port.uartclk = 921600*16; + } + uart_resume_port(&serial8250_reg, &up->port); + } +--- vanilla-2.6.38.0.orig/drivers/usb/serial/usb-serial.c ++++ vanilla-2.6.38.0/drivers/usb/serial/usb-serial.c +@@ -911,9 +911,8 @@ int usb_serial_probe(struct usb_interfac + dev_err(&interface->dev, "No free urbs available\n"); + goto probe_error; + } +- buffer_size = serial->type->bulk_in_size; +- if (!buffer_size) +- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); ++ buffer_size = max_t(int, serial->type->bulk_in_size, ++ le16_to_cpu(endpoint->wMaxPacketSize)); + port->bulk_in_size = buffer_size; + port->bulk_in_endpointAddress = endpoint->bEndpointAddress; + port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); +--- vanilla-2.6.38.0.orig/include/linux/usb/serial.h ++++ vanilla-2.6.38.0/include/linux/usb/serial.h +@@ -191,7 +191,8 @@ static inline void usb_set_serial_data(s + * @id_table: pointer to a list of usb_device_id structures that define all + * of the devices this structure can support. + * @num_ports: the number of different ports this device will have. +- * @bulk_in_size: bytes to allocate for bulk-in buffer (0 = end-point size) ++ * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer ++ * (0 = end-point size) + * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size) + * @calc_num_ports: pointer to a function to determine how many ports this + * device has dynamically. It will be called after the probe() +--- vanilla-2.6.38.0.orig/drivers/usb/serial/kobil_sct.c ++++ vanilla-2.6.38.0/drivers/usb/serial/kobil_sct.c +@@ -372,7 +372,7 @@ static void kobil_read_int_callback(stru + } + + tty = tty_port_tty_get(&port->port); +- if (urb->actual_length) { ++ if (tty && urb->actual_length) { + + /* BEGIN DEBUG */ + /* +--- vanilla-2.6.38.0.orig/drivers/usb/serial/option.c ++++ vanilla-2.6.38.0/drivers/usb/serial/option.c +@@ -652,7 +652,8 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, ++ 0xff, 0xff), .driver_info = (kernel_ulong_t)&four_g_w14_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) }, +--- vanilla-2.6.38.0.orig/drivers/usb/serial/ch341.c ++++ vanilla-2.6.38.0/drivers/usb/serial/ch341.c +@@ -75,6 +75,7 @@ static int debug; + static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x4348, 0x5523) }, + { USB_DEVICE(0x1a86, 0x7523) }, ++ { USB_DEVICE(0x1a86, 0x5523) }, + { }, + }; + MODULE_DEVICE_TABLE(usb, id_table); +--- vanilla-2.6.38.0.orig/drivers/staging/winbond/core.h ++++ vanilla-2.6.38.0/drivers/staging/winbond/core.h +@@ -3,6 +3,7 @@ + + #include + #include ++#include + + #include "wbhal.h" + #include "mto.h" +--- vanilla-2.6.38.0.orig/drivers/staging/tidspbridge/rmgr/proc.c ++++ vanilla-2.6.38.0/drivers/staging/tidspbridge/rmgr/proc.c +@@ -781,12 +781,14 @@ int proc_begin_dma(void *hprocessor, voi + (u32)pmpu_addr, + ul_size, dir); + ++ mutex_lock(&proc_lock); ++ + /* find requested memory are in cached mapping information */ + map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size); + if (!map_obj) { + pr_err("%s: find_containing_mapping failed\n", __func__); + status = -EFAULT; +- goto err_out; ++ goto no_map; + } + + if (memory_give_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) { +@@ -795,6 +797,8 @@ int proc_begin_dma(void *hprocessor, voi + status = -EFAULT; + } + ++no_map: ++ mutex_unlock(&proc_lock); + err_out: + + return status; +@@ -819,21 +823,24 @@ int proc_end_dma(void *hprocessor, void + (u32)pmpu_addr, + ul_size, dir); + ++ mutex_lock(&proc_lock); ++ + /* find requested memory are in cached mapping information */ + map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size); + if (!map_obj) { + pr_err("%s: find_containing_mapping failed\n", __func__); + status = -EFAULT; +- goto err_out; ++ goto no_map; + } + + if (memory_regain_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) { + pr_err("%s: InValid address parameters %p %x\n", + __func__, pmpu_addr, ul_size); + status = -EFAULT; +- goto err_out; + } + ++no_map: ++ mutex_unlock(&proc_lock); + err_out: + return status; + } +@@ -1726,9 +1733,8 @@ int proc_un_map(void *hprocessor, void * + (p_proc_object->hbridge_context, va_align, size_align); + } + +- mutex_unlock(&proc_lock); + if (status) +- goto func_end; ++ goto unmap_failed; + + /* + * A successful unmap should be followed by removal of map_obj +@@ -1737,6 +1743,9 @@ int proc_un_map(void *hprocessor, void * + */ + remove_mapping_information(pr_ctxt, (u32) map_addr, size_align); + ++unmap_failed: ++ mutex_unlock(&proc_lock); ++ + func_end: + dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n", + __func__, hprocessor, map_addr, status); +--- vanilla-2.6.38.0.orig/drivers/net/wireless/rtl818x/rtl8187/dev.c ++++ vanilla-2.6.38.0/drivers/net/wireless/rtl818x/rtl8187/dev.c +@@ -871,23 +871,35 @@ static void rtl8187_work(struct work_str + /* The RTL8187 returns the retry count through register 0xFFFA. In + * addition, it appears to be a cumulative retry count, not the + * value for the current TX packet. When multiple TX entries are +- * queued, the retry count will be valid for the last one in the queue. +- * The "error" should not matter for purposes of rate setting. */ ++ * waiting in the queue, the retry count will be the total for all. ++ * The "error" may matter for purposes of rate setting, but there is ++ * no other choice with this hardware. ++ */ + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + work.work); + struct ieee80211_tx_info *info; + struct ieee80211_hw *dev = priv->dev; + static u16 retry; + u16 tmp; ++ u16 avg_retry; ++ int length; + + mutex_lock(&priv->conf_mutex); + tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA); ++ length = skb_queue_len(&priv->b_tx_status.queue); ++ if (unlikely(!length)) ++ length = 1; ++ if (unlikely(tmp < retry)) ++ tmp = retry; ++ avg_retry = (tmp - retry) / length; + while (skb_queue_len(&priv->b_tx_status.queue) > 0) { + struct sk_buff *old_skb; + + old_skb = skb_dequeue(&priv->b_tx_status.queue); + info = IEEE80211_SKB_CB(old_skb); +- info->status.rates[0].count = tmp - retry + 1; ++ info->status.rates[0].count = avg_retry + 1; ++ if (info->status.rates[0].count > RETRY_COUNT) ++ info->flags &= ~IEEE80211_TX_STAT_ACK; + ieee80211_tx_status_irqsafe(dev, old_skb); + } + retry = tmp; +@@ -933,8 +945,8 @@ static int rtl8187_start(struct ieee8021 + rtl818x_iowrite32(priv, &priv->map->TX_CONF, + RTL818X_TX_CONF_HW_SEQNUM | + RTL818X_TX_CONF_DISREQQSIZE | +- (7 << 8 /* short retry limit */) | +- (7 << 0 /* long retry limit */) | ++ (RETRY_COUNT << 8 /* short retry limit */) | ++ (RETRY_COUNT << 0 /* long retry limit */) | + (7 << 21 /* MAX TX DMA */)); + rtl8187_init_urbs(dev); + rtl8187b_init_status_urb(dev); +@@ -1378,6 +1390,9 @@ static int __devinit rtl8187_probe(struc + dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_RX_INCLUDES_FCS; ++ /* Initialize rate-control variables */ ++ dev->max_rates = 1; ++ dev->max_rate_tries = RETRY_COUNT; + + eeprom.data = dev; + eeprom.register_read = rtl8187_eeprom_register_read; +--- vanilla-2.6.38.0.orig/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h ++++ vanilla-2.6.38.0/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +@@ -35,6 +35,8 @@ + #define RFKILL_MASK_8187_89_97 0x2 + #define RFKILL_MASK_8198 0x4 + ++#define RETRY_COUNT 7 ++ + struct rtl8187_rx_info { + struct urb *urb; + struct ieee80211_hw *dev; +--- vanilla-2.6.38.0.orig/drivers/usb/host/isp1760-hcd.c ++++ vanilla-2.6.38.0/drivers/usb/host/isp1760-hcd.c +@@ -33,6 +33,7 @@ struct isp1760_hcd { + struct inter_packet_info atl_ints[32]; + struct inter_packet_info int_ints[32]; + struct memory_chunk memory_pool[BLOCKS]; ++ u32 atl_queued; + + /* periodic schedule support */ + #define DEFAULT_I_TDPS 1024 +@@ -850,6 +851,11 @@ static void enqueue_an_ATL_packet(struct + skip_map &= ~queue_entry; + isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG); + ++ priv->atl_queued++; ++ if (priv->atl_queued == 2) ++ isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, ++ hcd->regs + HC_INTERRUPT_ENABLE); ++ + buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG); + buffstatus |= ATL_BUFFER; + isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG); +@@ -992,6 +998,7 @@ static void do_atl_int(struct usb_hcd *u + u32 dw3; + + status = 0; ++ priv->atl_queued--; + + queue_entry = __ffs(done_map); + done_map &= ~(1 << queue_entry); +@@ -1054,11 +1061,6 @@ static void do_atl_int(struct usb_hcd *u + * device is not able to send data fast enough. + * This happens mostly on slower hardware. + */ +- printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: " +- "%d of %zu done: %08x cur: %08x\n", qtd, +- urb, qh, PTD_XFERRED_LENGTH(dw3), +- qtd->length, done_map, +- (1 << queue_entry)); + + /* RL counter = ERR counter */ + dw3 &= ~(0xf << 19); +@@ -1086,6 +1088,11 @@ static void do_atl_int(struct usb_hcd *u + priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + + atl_regs, sizeof(ptd)); + ++ priv->atl_queued++; ++ if (priv->atl_queued == 2) ++ isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, ++ usb_hcd->regs + HC_INTERRUPT_ENABLE); ++ + buffstatus = isp1760_readl(usb_hcd->regs + + HC_BUFFER_STATUS_REG); + buffstatus |= ATL_BUFFER; +@@ -1191,6 +1198,9 @@ static void do_atl_int(struct usb_hcd *u + skip_map = isp1760_readl(usb_hcd->regs + + HC_ATL_PTD_SKIPMAP_REG); + } ++ if (priv->atl_queued <= 1) ++ isp1760_writel(INTERRUPT_ENABLE_MASK, ++ usb_hcd->regs + HC_INTERRUPT_ENABLE); + } + + static void do_intl_int(struct usb_hcd *usb_hcd) +@@ -1770,7 +1780,7 @@ static irqreturn_t isp1760_irq(struct us + goto leave; + + isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG); +- if (imask & HC_ATL_INT) ++ if (imask & (HC_ATL_INT | HC_SOT_INT)) + do_atl_int(usb_hcd); + + if (imask & HC_INTL_INT) +--- vanilla-2.6.38.0.orig/drivers/usb/host/isp1760-hcd.h ++++ vanilla-2.6.38.0/drivers/usb/host/isp1760-hcd.h +@@ -69,6 +69,7 @@ void deinit_kmem_cache(void); + + #define HC_INTERRUPT_ENABLE 0x314 + #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) ++#define INTERRUPT_ENABLE_SOT_MASK (HC_INTL_INT | HC_SOT_INT | HC_EOT_INT) + + #define HC_ISO_INT (1 << 9) + #define HC_ATL_INT (1 << 8) +--- vanilla-2.6.38.0.orig/drivers/usb/host/ehci-hub.c ++++ vanilla-2.6.38.0/drivers/usb/host/ehci-hub.c +@@ -106,6 +106,27 @@ static void ehci_handover_companion_port + ehci->owned_ports = 0; + } + ++static int ehci_port_change(struct ehci_hcd *ehci) ++{ ++ int i = HCS_N_PORTS(ehci->hcs_params); ++ ++ /* First check if the controller indicates a change event */ ++ ++ if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD) ++ return 1; ++ ++ /* ++ * Not all controllers appear to update this while going from D3 to D0, ++ * so check the individual port status registers as well ++ */ ++ ++ while (i--) ++ if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC) ++ return 1; ++ ++ return 0; ++} ++ + static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, + bool suspending, bool do_wakeup) + { +@@ -173,7 +194,7 @@ static void ehci_adjust_port_wakeup_flag + } + + /* Does the root hub have a port wakeup pending? */ +- if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)) ++ if (!suspending && ehci_port_change(ehci)) + usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); + + spin_unlock_irqrestore(&ehci->lock, flags); +--- vanilla-2.6.38.0.orig/drivers/usb/core/hcd-pci.c ++++ vanilla-2.6.38.0/drivers/usb/core/hcd-pci.c +@@ -363,8 +363,7 @@ static int check_root_hub_suspended(stru + struct pci_dev *pci_dev = to_pci_dev(dev); + struct usb_hcd *hcd = pci_get_drvdata(pci_dev); + +- if (!(hcd->state == HC_STATE_SUSPENDED || +- hcd->state == HC_STATE_HALT)) { ++ if (HCD_RH_RUNNING(hcd)) { + dev_warn(dev, "Root hub is not suspended\n"); + return -EBUSY; + } +@@ -386,7 +385,7 @@ static int suspend_common(struct device + if (retval) + return retval; + +- if (hcd->driver->pci_suspend) { ++ if (hcd->driver->pci_suspend && !HCD_DEAD(hcd)) { + /* Optimization: Don't suspend if a root-hub wakeup is + * pending and it would cause the HCD to wake up anyway. + */ +@@ -427,7 +426,7 @@ static int resume_common(struct device * + struct usb_hcd *hcd = pci_get_drvdata(pci_dev); + int retval; + +- if (hcd->state != HC_STATE_SUSPENDED) { ++ if (HCD_RH_RUNNING(hcd)) { + dev_dbg(dev, "can't resume, not suspended!\n"); + return 0; + } +@@ -442,7 +441,7 @@ static int resume_common(struct device * + + clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + +- if (hcd->driver->pci_resume) { ++ if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) { + if (event != PM_EVENT_AUTO_RESUME) + wait_for_companions(pci_dev, hcd); + +@@ -475,10 +474,10 @@ static int hcd_pci_suspend_noirq(struct + + pci_save_state(pci_dev); + +- /* If the root hub is HALTed rather than SUSPENDed, ++ /* If the root hub is dead rather than suspended, + * disallow remote wakeup. + */ +- if (hcd->state == HC_STATE_HALT) ++ if (HCD_DEAD(hcd)) + device_set_wakeup_enable(dev, 0); + dev_dbg(dev, "wakeup: %d\n", device_may_wakeup(dev)); + +--- vanilla-2.6.38.0.orig/drivers/usb/core/hcd.c ++++ vanilla-2.6.38.0/drivers/usb/core/hcd.c +@@ -983,7 +983,7 @@ static int register_root_hub(struct usb_ + spin_unlock_irq (&hcd_root_hub_lock); + + /* Did the HC die before the root hub was registered? */ +- if (hcd->state == HC_STATE_HALT) ++ if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT) + usb_hc_died (hcd); /* This time clean up */ + } + +@@ -1089,13 +1089,10 @@ int usb_hcd_link_urb_to_ep(struct usb_hc + * Check the host controller's state and add the URB to the + * endpoint's queue. + */ +- switch (hcd->state) { +- case HC_STATE_RUNNING: +- case HC_STATE_RESUMING: ++ if (HCD_RH_RUNNING(hcd)) { + urb->unlinked = 0; + list_add_tail(&urb->urb_list, &urb->ep->urb_list); +- break; +- default: ++ } else { + rc = -ESHUTDOWN; + goto done; + } +@@ -1913,7 +1910,7 @@ int usb_hcd_get_frame_number (struct usb + { + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + +- if (!HC_IS_RUNNING (hcd->state)) ++ if (!HCD_RH_RUNNING(hcd)) + return -ESHUTDOWN; + return hcd->driver->get_frame_number (hcd); + } +@@ -1930,9 +1927,15 @@ int hcd_bus_suspend(struct usb_device *r + + dev_dbg(&rhdev->dev, "bus %s%s\n", + (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend"); ++ if (HCD_DEAD(hcd)) { ++ dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend"); ++ return 0; ++ } ++ + if (!hcd->driver->bus_suspend) { + status = -ENOENT; + } else { ++ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); + hcd->state = HC_STATE_QUIESCING; + status = hcd->driver->bus_suspend(hcd); + } +@@ -1940,7 +1943,12 @@ int hcd_bus_suspend(struct usb_device *r + usb_set_device_state(rhdev, USB_STATE_SUSPENDED); + hcd->state = HC_STATE_SUSPENDED; + } else { +- hcd->state = old_state; ++ spin_lock_irq(&hcd_root_hub_lock); ++ if (!HCD_DEAD(hcd)) { ++ set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); ++ hcd->state = old_state; ++ } ++ spin_unlock_irq(&hcd_root_hub_lock); + dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", + "suspend", status); + } +@@ -1955,9 +1963,13 @@ int hcd_bus_resume(struct usb_device *rh + + dev_dbg(&rhdev->dev, "usb %s%s\n", + (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); ++ if (HCD_DEAD(hcd)) { ++ dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume"); ++ return 0; ++ } + if (!hcd->driver->bus_resume) + return -ENOENT; +- if (hcd->state == HC_STATE_RUNNING) ++ if (HCD_RH_RUNNING(hcd)) + return 0; + + hcd->state = HC_STATE_RESUMING; +@@ -1966,10 +1978,15 @@ int hcd_bus_resume(struct usb_device *rh + if (status == 0) { + /* TRSMRCY = 10 msec */ + msleep(10); +- usb_set_device_state(rhdev, rhdev->actconfig +- ? USB_STATE_CONFIGURED +- : USB_STATE_ADDRESS); +- hcd->state = HC_STATE_RUNNING; ++ spin_lock_irq(&hcd_root_hub_lock); ++ if (!HCD_DEAD(hcd)) { ++ usb_set_device_state(rhdev, rhdev->actconfig ++ ? USB_STATE_CONFIGURED ++ : USB_STATE_ADDRESS); ++ set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); ++ hcd->state = HC_STATE_RUNNING; ++ } ++ spin_unlock_irq(&hcd_root_hub_lock); + } else { + hcd->state = old_state; + dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", +@@ -2080,7 +2097,7 @@ irqreturn_t usb_hcd_irq (int irq, void * + */ + local_irq_save(flags); + +- if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) { ++ if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) { + rc = IRQ_NONE; + } else if (hcd->driver->irq(hcd) == IRQ_NONE) { + rc = IRQ_NONE; +@@ -2114,6 +2131,8 @@ void usb_hc_died (struct usb_hcd *hcd) + dev_err (hcd->self.controller, "HC died; cleaning up\n"); + + spin_lock_irqsave (&hcd_root_hub_lock, flags); ++ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); ++ set_bit(HCD_FLAG_DEAD, &hcd->flags); + if (hcd->rh_registered) { + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + +@@ -2256,6 +2275,12 @@ int usb_add_hcd(struct usb_hcd *hcd, + */ + device_init_wakeup(&rhdev->dev, 1); + ++ /* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is ++ * registered. But since the controller can die at any time, ++ * let's initialize the flag before touching the hardware. ++ */ ++ set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); ++ + /* "reset" is misnamed; its role is now one-time init. the controller + * should already have been reset (and boot firmware kicked off etc). + */ +@@ -2323,6 +2348,7 @@ int usb_add_hcd(struct usb_hcd *hcd, + return retval; + + error_create_attr_group: ++ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); + if (HC_IS_RUNNING(hcd->state)) + hcd->state = HC_STATE_QUIESCING; + spin_lock_irq(&hcd_root_hub_lock); +@@ -2375,6 +2401,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) + usb_get_dev(rhdev); + sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group); + ++ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); + if (HC_IS_RUNNING (hcd->state)) + hcd->state = HC_STATE_QUIESCING; + +--- vanilla-2.6.38.0.orig/include/linux/usb/hcd.h ++++ vanilla-2.6.38.0/include/linux/usb/hcd.h +@@ -99,6 +99,8 @@ struct usb_hcd { + #define HCD_FLAG_POLL_RH 2 /* poll for rh status? */ + #define HCD_FLAG_POLL_PENDING 3 /* status has changed? */ + #define HCD_FLAG_WAKEUP_PENDING 4 /* root hub is resuming? */ ++#define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */ ++#define HCD_FLAG_DEAD 6 /* controller has died? */ + + /* The flags can be tested using these macros; they are likely to + * be slightly faster than test_bit(). +@@ -108,6 +110,8 @@ struct usb_hcd { + #define HCD_POLL_RH(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_RH)) + #define HCD_POLL_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING)) + #define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING)) ++#define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING)) ++#define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD)) + + /* Flags that get set only during HCD registration or removal. */ + unsigned rh_registered:1;/* is root hub registered? */ +--- vanilla-2.6.38.0.orig/drivers/usb/host/xhci-ring.c ++++ vanilla-2.6.38.0/drivers/usb/host/xhci-ring.c +@@ -500,15 +500,26 @@ void xhci_find_new_dequeue_state(struct + state->new_cycle_state = ~(state->new_cycle_state) & 0x1; + next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr); + ++ /* ++ * If there is only one segment in a ring, find_trb_seg()'s while loop ++ * will not run, and it will return before it has a chance to see if it ++ * needs to toggle the cycle bit. It can't tell if the stalled transfer ++ * ended just before the link TRB on a one-segment ring, or if the TD ++ * wrapped around the top of the ring, because it doesn't have the TD in ++ * question. Look for the one-segment case where stalled TRB's address ++ * is greater than the new dequeue pointer address. ++ */ ++ if (ep_ring->first_seg == ep_ring->first_seg->next && ++ state->new_deq_ptr < dev->eps[ep_index].stopped_trb) ++ state->new_cycle_state ^= 0x1; ++ xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state); ++ + /* Don't update the ring cycle state for the producer (us). */ + xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n", + state->new_deq_seg); + addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr); + xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n", + (unsigned long long) addr); +- xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n"); +- ep_ring->dequeue = state->new_deq_ptr; +- ep_ring->deq_seg = state->new_deq_seg; + } + + static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, +@@ -951,9 +962,26 @@ static void handle_set_deq_completion(st + } else { + xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n", + ep_ctx->deq); ++ if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg, ++ dev->eps[ep_index].queued_deq_ptr) == ++ (ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) { ++ /* Update the ring's dequeue segment and dequeue pointer ++ * to reflect the new position. ++ */ ++ ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg; ++ ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr; ++ } else { ++ xhci_warn(xhci, "Mismatch between completed Set TR Deq " ++ "Ptr command & xHCI internal state.\n"); ++ xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n", ++ dev->eps[ep_index].queued_deq_seg, ++ dev->eps[ep_index].queued_deq_ptr); ++ } + } + + dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING; ++ dev->eps[ep_index].queued_deq_seg = NULL; ++ dev->eps[ep_index].queued_deq_ptr = NULL; + /* Restart any rings with pending URBs */ + ring_doorbell_for_active_rings(xhci, slot_id, ep_index); + } +@@ -3229,6 +3257,7 @@ static int queue_set_tr_deq(struct xhci_ + u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); + u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id); + u32 type = TRB_TYPE(TRB_SET_DEQ); ++ struct xhci_virt_ep *ep; + + addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr); + if (addr == 0) { +@@ -3237,6 +3266,14 @@ static int queue_set_tr_deq(struct xhci_ + deq_seg, deq_ptr); + return 0; + } ++ ep = &xhci->devs[slot_id]->eps[ep_index]; ++ if ((ep->ep_state & SET_DEQ_PENDING)) { ++ xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n"); ++ xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n"); ++ return 0; ++ } ++ ep->queued_deq_seg = deq_seg; ++ ep->queued_deq_ptr = deq_ptr; + return queue_command(xhci, lower_32_bits(addr) | cycle_state, + upper_32_bits(addr), trb_stream_id, + trb_slot_id | trb_ep_index | type, false); +--- vanilla-2.6.38.0.orig/drivers/usb/host/xhci.h ++++ vanilla-2.6.38.0/drivers/usb/host/xhci.h +@@ -644,6 +644,9 @@ struct xhci_ep_ctx { + #define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) + #define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) + ++/* deq bitmasks */ ++#define EP_CTX_CYCLE_MASK (1 << 0) ++ + + /** + * struct xhci_input_control_context +@@ -746,6 +749,12 @@ struct xhci_virt_ep { + struct timer_list stop_cmd_timer; + int stop_cmds_pending; + struct xhci_hcd *xhci; ++ /* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue ++ * command. We'll need to update the ring's dequeue segment and dequeue ++ * pointer after the command completes. ++ */ ++ struct xhci_segment *queued_deq_seg; ++ union xhci_trb *queued_deq_ptr; + /* + * Sometimes the xHC can not process isochronous endpoint ring quickly + * enough, and it will miss some isoc tds on the ring and generate +--- vanilla-2.6.38.0.orig/drivers/usb/core/urb.c ++++ vanilla-2.6.38.0/drivers/usb/core/urb.c +@@ -366,7 +366,16 @@ int usb_submit_urb(struct urb *urb, gfp_ + if (xfertype == USB_ENDPOINT_XFER_ISOC) { + int n, len; + +- /* FIXME SuperSpeed isoc endpoints have up to 16 bursts */ ++ /* SuperSpeed isoc endpoints have up to 16 bursts of up to ++ * 3 packets each ++ */ ++ if (dev->speed == USB_SPEED_SUPER) { ++ int burst = 1 + ep->ss_ep_comp.bMaxBurst; ++ int mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes); ++ max *= burst; ++ max *= mult; ++ } ++ + /* "high bandwidth" mode, 1-3 packets/uframe? */ + if (dev->speed == USB_SPEED_HIGH) { + int mult = 1 + ((max >> 11) & 0x03); +--- vanilla-2.6.38.0.orig/include/linux/usb/ch9.h ++++ vanilla-2.6.38.0/include/linux/usb/ch9.h +@@ -585,6 +585,8 @@ struct usb_ss_ep_comp_descriptor { + #define USB_DT_SS_EP_COMP_SIZE 6 + /* Bits 4:0 of bmAttributes if this is a bulk endpoint */ + #define USB_SS_MAX_STREAMS(p) (1 << (p & 0x1f)) ++/* Bits 1:0 of bmAttributes if this is an isoc endpoint */ ++#define USB_SS_MULT(p) (1 + ((p) & 0x3)) + + /*-------------------------------------------------------------------------*/ + +--- vanilla-2.6.38.0.orig/sound/pci/hda/patch_realtek.c ++++ vanilla-2.6.38.0/sound/pci/hda/patch_realtek.c +@@ -394,6 +394,7 @@ struct alc_spec { + /* other flags */ + unsigned int no_analog :1; /* digital I/O only */ + unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ ++ unsigned int single_input_src:1; + int init_amp; + int codec_variant; /* flag for other variants */ + +@@ -3919,6 +3920,8 @@ static struct hda_amp_list alc880_lg_loo + * Common callbacks + */ + ++static void alc_init_special_input_src(struct hda_codec *codec); ++ + static int alc_init(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +@@ -3929,6 +3932,7 @@ static int alc_init(struct hda_codec *co + + for (i = 0; i < spec->num_init_verbs; i++) + snd_hda_sequence_write(codec, spec->init_verbs[i]); ++ alc_init_special_input_src(codec); + + if (spec->init_hook) + spec->init_hook(codec); +@@ -5151,7 +5155,9 @@ static const char *alc_get_line_out_pfx( + + switch (cfg->line_out_type) { + case AUTO_PIN_SPEAKER_OUT: +- return "Speaker"; ++ if (cfg->line_outs == 1) ++ return "Speaker"; ++ break; + case AUTO_PIN_HP_OUT: + return "Headphone"; + default: +@@ -5205,16 +5211,19 @@ static int alc880_auto_create_multi_out_ + return err; + } else { + const char *name = pfx; +- if (!name) ++ int index = i; ++ if (!name) { + name = chname[i]; ++ index = 0; ++ } + err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, +- name, i, ++ name, index, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, + HDA_OUTPUT)); + if (err < 0) + return err; + err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, +- name, i, ++ name, index, + HDA_COMPOSE_AMP_VAL(nid, 3, 2, + HDA_INPUT)); + if (err < 0) +@@ -5585,6 +5594,7 @@ static void fixup_single_adc(struct hda_ + spec->capsrc_nids += i; + spec->adc_nids += i; + spec->num_adc_nids = 1; ++ spec->single_input_src = 1; + } + } + +@@ -5596,6 +5606,16 @@ static void fixup_dual_adc_switch(struct + init_capsrc_for_pin(codec, spec->int_mic.pin); + } + ++/* initialize some special cases for input sources */ ++static void alc_init_special_input_src(struct hda_codec *codec) ++{ ++ struct alc_spec *spec = codec->spec; ++ if (spec->dual_adc_switch) ++ fixup_dual_adc_switch(codec); ++ else if (spec->single_input_src) ++ init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin); ++} ++ + static void set_capture_mixer(struct hda_codec *codec) + { + struct alc_spec *spec = codec->spec; +@@ -5611,7 +5631,7 @@ static void set_capture_mixer(struct hda + int mux = 0; + int num_adcs = spec->num_adc_nids; + if (spec->dual_adc_switch) +- fixup_dual_adc_switch(codec); ++ num_adcs = 1; + else if (spec->auto_mic) + fixup_automic_adc(codec); + else if (spec->input_mux) { +@@ -5620,8 +5640,6 @@ static void set_capture_mixer(struct hda + else if (spec->input_mux->num_items == 1) + fixup_single_adc(codec); + } +- if (spec->dual_adc_switch) +- num_adcs = 1; + spec->cap_mixer = caps[mux][num_adcs - 1]; + } + } +@@ -10748,6 +10766,7 @@ static struct alc_config_preset alc882_p + */ + enum { + PINFIX_ABIT_AW9D_MAX, ++ PINFIX_LENOVO_Y530, + PINFIX_PB_M5210, + PINFIX_ACER_ASPIRE_7736, + }; +@@ -10762,6 +10781,14 @@ static const struct alc_fixup alc882_fix + { } + } + }, ++ [PINFIX_LENOVO_Y530] = { ++ .type = ALC_FIXUP_PINS, ++ .v.pins = (const struct alc_pincfg[]) { ++ { 0x15, 0x99130112 }, /* rear int speakers */ ++ { 0x16, 0x99130111 }, /* subwoofer */ ++ { } ++ } ++ }, + [PINFIX_PB_M5210] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { +@@ -10777,6 +10804,7 @@ static const struct alc_fixup alc882_fix + + static struct snd_pci_quirk alc882_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), ++ SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530), + SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), + SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736), + {} +@@ -10829,23 +10857,28 @@ static void alc882_auto_init_hp_out(stru + hda_nid_t pin, dac; + int i; + +- for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { +- pin = spec->autocfg.hp_pins[i]; +- if (!pin) +- break; +- dac = spec->multiout.hp_nid; +- if (!dac) +- dac = spec->multiout.dac_nids[0]; /* to front */ +- alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); ++ if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) { ++ for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { ++ pin = spec->autocfg.hp_pins[i]; ++ if (!pin) ++ break; ++ dac = spec->multiout.hp_nid; ++ if (!dac) ++ dac = spec->multiout.dac_nids[0]; /* to front */ ++ alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); ++ } + } +- for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { +- pin = spec->autocfg.speaker_pins[i]; +- if (!pin) +- break; +- dac = spec->multiout.extra_out_nid[0]; +- if (!dac) +- dac = spec->multiout.dac_nids[0]; /* to front */ +- alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); ++ ++ if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) { ++ for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { ++ pin = spec->autocfg.speaker_pins[i]; ++ if (!pin) ++ break; ++ dac = spec->multiout.extra_out_nid[0]; ++ if (!dac) ++ dac = spec->multiout.dac_nids[0]; /* to front */ ++ alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); ++ } + } + } + +--- vanilla-2.6.38.0.orig/sound/pci/hda/patch_sigmatel.c ++++ vanilla-2.6.38.0/sound/pci/hda/patch_sigmatel.c +@@ -757,7 +757,7 @@ static int stac92xx_mux_enum_put(struct + struct sigmatel_spec *spec = codec->spec; + unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); + const struct hda_input_mux *imux = spec->input_mux; +- unsigned int idx, prev_idx; ++ unsigned int idx, prev_idx, didx; + + idx = ucontrol->value.enumerated.item[0]; + if (idx >= imux->num_items) +@@ -769,7 +769,8 @@ static int stac92xx_mux_enum_put(struct + snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, + AC_VERB_SET_CONNECT_SEL, + imux->items[idx].index); +- if (prev_idx >= spec->num_analog_muxes) { ++ if (prev_idx >= spec->num_analog_muxes && ++ spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) { + imux = spec->dinput_mux; + /* 0 = analog */ + snd_hda_codec_write_cache(codec, +@@ -779,9 +780,13 @@ static int stac92xx_mux_enum_put(struct + } + } else { + imux = spec->dinput_mux; ++ /* first dimux item is hardcoded to select analog imux, ++ * so lets skip it ++ */ ++ didx = idx - spec->num_analog_muxes + 1; + snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, + AC_VERB_SET_CONNECT_SEL, +- imux->items[idx - 1].index); ++ imux->items[didx].index); + } + spec->cur_mux[adc_idx] = idx; + return 1; +--- vanilla-2.6.38.0.orig/drivers/hid/hid-magicmouse.c ++++ vanilla-2.6.38.0/drivers/hid/hid-magicmouse.c +@@ -258,7 +258,7 @@ static void magicmouse_emit_touch(struct + input_report_abs(input, ABS_MT_TRACKING_ID, id); + input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); + input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); +- input_report_abs(input, ABS_MT_ORIENTATION, orientation); ++ input_report_abs(input, ABS_MT_ORIENTATION, -orientation); + input_report_abs(input, ABS_MT_POSITION_X, x); + input_report_abs(input, ABS_MT_POSITION_Y, y); + +@@ -397,7 +397,7 @@ static void magicmouse_setup_input(struc + input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0); + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); + input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); +- input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0); ++ input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0); + + /* Note: Touch Y position from the device is inverted relative + * to how pointer motion is reported (and relative to how USB +--- vanilla-2.6.38.0.orig/drivers/hid/Kconfig ++++ vanilla-2.6.38.0/drivers/hid/Kconfig +@@ -68,9 +68,15 @@ config HID_A4TECH + ---help--- + Support for A4 tech X5 and WOP-35 / Trust 450L mice. + +-config HID_ACRUX_FF +- tristate "ACRUX force feedback" ++config HID_ACRUX ++ tristate "ACRUX game controller support" + depends on USB_HID ++ ---help--- ++ Say Y here if you want to enable support for ACRUX game controllers. ++ ++config HID_ACRUX_FF ++ tristate "ACRUX force feedback support" ++ depends on HID_ACRUX + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you want to enable force feedback support for ACRUX +@@ -319,10 +325,10 @@ config HID_NTRIG + Support for N-Trig touch screen. + + config HID_ORTEK +- tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad" ++ tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad" + depends on USB_HID + ---help--- +- Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. ++ Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad. + + config HID_PANTHERLORD + tristate "Pantherlord/GreenAsia game controller" +--- vanilla-2.6.38.0.orig/drivers/hid/hid-core.c ++++ vanilla-2.6.38.0/drivers/hid/hid-core.c +@@ -1256,9 +1256,7 @@ static const struct hid_device_id hid_ha + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, + { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, +-#if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE) + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, +-#endif + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, +@@ -1302,6 +1300,9 @@ static const struct hid_device_id hid_ha + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, +@@ -1400,6 +1401,7 @@ static const struct hid_device_id hid_ha + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, +@@ -1801,6 +1803,9 @@ static const struct hid_device_id hid_mo + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { } +--- vanilla-2.6.38.0.orig/drivers/hid/hid-ids.h ++++ vanilla-2.6.38.0/drivers/hid/hid-ids.h +@@ -103,6 +103,9 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 + #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 + #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 ++#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 ++#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 ++#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 + #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 + #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a + #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b +@@ -466,6 +469,7 @@ + #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 + + #define USB_VENDOR_ID_ORTEK 0x05a4 ++#define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 + #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 + + #define USB_VENDOR_ID_PANJIT 0x134c +--- vanilla-2.6.38.0.orig/drivers/hid/hid-ortek.c ++++ vanilla-2.6.38.0/drivers/hid/hid-ortek.c +@@ -1,5 +1,5 @@ + /* +- * HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad). ++ * HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad). + * Fixes LogicalMaximum error in USB report description, see + * http://bugzilla.kernel.org/show_bug.cgi?id=14787 + * +@@ -30,6 +30,7 @@ static __u8 *ortek_report_fixup(struct h + } + + static const struct hid_device_id ortek_devices[] = { ++ { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, + { } + }; +--- vanilla-2.6.38.0.orig/drivers/pci/quirks.c ++++ vanilla-2.6.38.0/drivers/pci/quirks.c +@@ -533,6 +533,17 @@ static void __devinit quirk_piix4_acpi(s + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi); + ++#define ICH_PMBASE 0x40 ++#define ICH_ACPI_CNTL 0x44 ++#define ICH4_ACPI_EN 0x10 ++#define ICH6_ACPI_EN 0x80 ++#define ICH4_GPIOBASE 0x58 ++#define ICH4_GPIO_CNTL 0x5c ++#define ICH4_GPIO_EN 0x10 ++#define ICH6_GPIOBASE 0x48 ++#define ICH6_GPIO_CNTL 0x4c ++#define ICH6_GPIO_EN 0x10 ++ + /* + * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at + * 0x40 (128 bytes of ACPI, GPIO & TCO registers) +@@ -541,12 +552,33 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I + static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev) + { + u32 region; ++ u8 enable; + +- pci_read_config_dword(dev, 0x40, ®ion); +- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO"); ++ /* ++ * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict ++ * with low legacy (and fixed) ports. We don't know the decoding ++ * priority and can't tell whether the legacy device or the one created ++ * here is really at that address. This happens on boards with broken ++ * BIOSes. ++ */ ++ ++ pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); ++ if (enable & ICH4_ACPI_EN) { ++ pci_read_config_dword(dev, ICH_PMBASE, ®ion); ++ region &= PCI_BASE_ADDRESS_IO_MASK; ++ if (region >= PCIBIOS_MIN_IO) ++ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, ++ "ICH4 ACPI/GPIO/TCO"); ++ } + +- pci_read_config_dword(dev, 0x58, ®ion); +- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO"); ++ pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); ++ if (enable & ICH4_GPIO_EN) { ++ pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); ++ region &= PCI_BASE_ADDRESS_IO_MASK; ++ if (region >= PCIBIOS_MIN_IO) ++ quirk_io_region(dev, region, 64, ++ PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO"); ++ } + } + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi); +@@ -562,12 +594,25 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I + static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev) + { + u32 region; ++ u8 enable; + +- pci_read_config_dword(dev, 0x40, ®ion); +- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO"); ++ pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); ++ if (enable & ICH6_ACPI_EN) { ++ pci_read_config_dword(dev, ICH_PMBASE, ®ion); ++ region &= PCI_BASE_ADDRESS_IO_MASK; ++ if (region >= PCIBIOS_MIN_IO) ++ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, ++ "ICH6 ACPI/GPIO/TCO"); ++ } + +- pci_read_config_dword(dev, 0x48, ®ion); +- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO"); ++ pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); ++ if (enable & ICH4_GPIO_EN) { ++ pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); ++ region &= PCI_BASE_ADDRESS_IO_MASK; ++ if (region >= PCIBIOS_MIN_IO) ++ quirk_io_region(dev, region, 64, ++ PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO"); ++ } + } + + static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) +@@ -2618,58 +2663,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT + + #endif /* CONFIG_PCI_MSI */ + +-#ifdef CONFIG_PCI_IOV +- +-/* +- * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the +- * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the +- * old Flash Memory Space. +- */ +-static void __devinit quirk_i82576_sriov(struct pci_dev *dev) +-{ +- int pos, flags; +- u32 bar, start, size; +- +- if (PAGE_SIZE > 0x10000) +- return; +- +- flags = pci_resource_flags(dev, 0); +- if ((flags & PCI_BASE_ADDRESS_SPACE) != +- PCI_BASE_ADDRESS_SPACE_MEMORY || +- (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != +- PCI_BASE_ADDRESS_MEM_TYPE_32) +- return; +- +- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); +- if (!pos) +- return; +- +- pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar); +- if (bar & PCI_BASE_ADDRESS_MEM_MASK) +- return; +- +- start = pci_resource_start(dev, 1); +- size = pci_resource_len(dev, 1); +- if (!start || size != 0x400000 || start & (size - 1)) +- return; +- +- pci_resource_flags(dev, 1) = 0; +- pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0); +- pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start); +- pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2); +- +- dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n"); +-} +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov); +-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); +- +-#endif /* CONFIG_PCI_IOV */ +- + /* Allow manual resource allocation for PCI hotplug bridges + * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For + * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6), +--- vanilla-2.6.38.0.orig/drivers/pci/pci-sysfs.c ++++ vanilla-2.6.38.0/drivers/pci/pci-sysfs.c +@@ -1088,7 +1088,7 @@ static int pci_create_capabilities_sysfs + attr->write = write_vpd_attr; + retval = sysfs_create_bin_file(&dev->dev.kobj, attr); + if (retval) { +- kfree(dev->vpd->attr); ++ kfree(attr); + return retval; + } + dev->vpd->attr = attr; +--- vanilla-2.6.38.0.orig/sound/pci/asihpi/hpioctl.c ++++ vanilla-2.6.38.0/sound/pci/asihpi/hpioctl.c +@@ -155,6 +155,11 @@ long asihpi_hpi_ioctl(struct file *file, + goto out; + } + ++ if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) { ++ err = -EINVAL; ++ goto out; ++ } ++ + pa = &adapters[hm->h.adapter_index]; + hr->h.size = 0; + if (hm->h.object == HPI_OBJ_SUBSYSTEM) { +--- vanilla-2.6.38.0.orig/sound/drivers/aloop.c ++++ vanilla-2.6.38.0/sound/drivers/aloop.c +@@ -482,8 +482,9 @@ static unsigned int loopback_pos_update( + cable->streams[SNDRV_PCM_STREAM_CAPTURE]; + unsigned long delta_play = 0, delta_capt = 0; + unsigned int running; ++ unsigned long flags; + +- spin_lock(&cable->lock); ++ spin_lock_irqsave(&cable->lock, flags); + running = cable->running ^ cable->pause; + if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { + delta_play = jiffies - dpcm_play->last_jiffies; +@@ -495,10 +496,8 @@ static unsigned int loopback_pos_update( + dpcm_capt->last_jiffies += delta_capt; + } + +- if (delta_play == 0 && delta_capt == 0) { +- spin_unlock(&cable->lock); +- return running; +- } ++ if (delta_play == 0 && delta_capt == 0) ++ goto unlock; + + if (delta_play > delta_capt) { + loopback_bytepos_update(dpcm_play, delta_play - delta_capt, +@@ -510,14 +509,14 @@ static unsigned int loopback_pos_update( + delta_capt = delta_play; + } + +- if (delta_play == 0 && delta_capt == 0) { +- spin_unlock(&cable->lock); +- return running; +- } ++ if (delta_play == 0 && delta_capt == 0) ++ goto unlock; ++ + /* note delta_capt == delta_play at this moment */ + loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); + loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); +- spin_unlock(&cable->lock); ++ unlock: ++ spin_unlock_irqrestore(&cable->lock, flags); + return running; + } + +--- vanilla-2.6.38.0.orig/sound/pci/ctxfi/ctatc.c ++++ vanilla-2.6.38.0/sound/pci/ctxfi/ctatc.c +@@ -869,7 +869,7 @@ spdif_passthru_playback_setup(struct ct_ + mutex_lock(&atc->atc_mutex); + dao->ops->get_spos(dao, &status); + if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { +- status &= ((~IEC958_AES3_CON_FS) << 24); ++ status &= ~(IEC958_AES3_CON_FS << 24); + status |= (iec958_con_fs << 24); + dao->ops->set_spos(dao, status); + dao->ops->commit_write(dao); +--- vanilla-2.6.38.0.orig/sound/pci/ctxfi/ctmixer.c ++++ vanilla-2.6.38.0/sound/pci/ctxfi/ctmixer.c +@@ -566,19 +566,6 @@ static int ct_spdif_get_mask(struct snd_ + return 0; + } + +-static int ct_spdif_default_get(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF; +- +- ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; +- ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; +- ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; +- ucontrol->value.iec958.status[3] = (status >> 24) & 0xff; +- +- return 0; +-} +- + static int ct_spdif_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { +@@ -586,6 +573,10 @@ static int ct_spdif_get(struct snd_kcont + unsigned int status; + + atc->spdif_out_get_status(atc, &status); ++ ++ if (status == 0) ++ status = SNDRV_PCM_DEFAULT_CON_SPDIF; ++ + ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; + ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; + ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; +@@ -629,7 +620,7 @@ static struct snd_kcontrol_new iec958_de + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), + .count = 1, + .info = ct_spdif_info, +- .get = ct_spdif_default_get, ++ .get = ct_spdif_get, + .put = ct_spdif_put, + .private_value = MIXER_IEC958_DEFAULT + }; +--- vanilla-2.6.38.0.orig/sound/pci/ctxfi/ctdaio.c ++++ vanilla-2.6.38.0/sound/pci/ctxfi/ctdaio.c +@@ -176,6 +176,7 @@ static int dao_set_left_input(struct dao + if (!entry) + return -ENOMEM; + ++ dao->ops->clear_left_input(dao); + /* Program master and conjugate resources */ + input->ops->master(input); + daio->rscl.ops->master(&daio->rscl); +@@ -204,6 +205,7 @@ static int dao_set_right_input(struct da + if (!entry) + return -ENOMEM; + ++ dao->ops->clear_right_input(dao); + /* Program master and conjugate resources */ + input->ops->master(input); + daio->rscr.ops->master(&daio->rscr); +--- vanilla-2.6.38.0.orig/sound/soc/pxa/z2.c ++++ vanilla-2.6.38.0/sound/soc/pxa/z2.c +@@ -147,7 +147,7 @@ static int z2_wm8750_init(struct snd_soc + snd_soc_dapm_disable_pin(dapm, "LINPUT3"); + snd_soc_dapm_disable_pin(dapm, "RINPUT3"); + snd_soc_dapm_disable_pin(dapm, "OUT3"); +- snd_soc_dapm_disable_pin(dapm, "MONO"); ++ snd_soc_dapm_disable_pin(dapm, "MONO1"); + + /* Add z2 specific widgets */ + snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets, +--- vanilla-2.6.38.0.orig/drivers/target/target_core_cdb.c ++++ vanilla-2.6.38.0/drivers/target/target_core_cdb.c +@@ -667,7 +667,13 @@ target_emulate_readcapacity(struct se_cm + { + struct se_device *dev = SE_DEV(cmd); + unsigned char *buf = cmd->t_task->t_task_buf; +- u32 blocks = dev->transport->get_blocks(dev); ++ unsigned long long blocks_long = dev->transport->get_blocks(dev); ++ u32 blocks; ++ ++ if (blocks_long >= 0x00000000ffffffff) ++ blocks = 0xffffffff; ++ else ++ blocks = (u32)blocks_long; + + buf[0] = (blocks >> 24) & 0xff; + buf[1] = (blocks >> 16) & 0xff; +--- vanilla-2.6.38.0.orig/drivers/scsi/device_handler/scsi_dh_alua.c ++++ vanilla-2.6.38.0/drivers/scsi/device_handler/scsi_dh_alua.c +@@ -285,7 +285,8 @@ static void stpg_endio(struct request *r + print_alua_state(h->state)); + } + done: +- blk_put_request(req); ++ req->end_io_data = NULL; ++ __blk_put_request(req->q, req); + if (h->callback_fn) { + h->callback_fn(h->callback_data, err); + h->callback_fn = h->callback_data = NULL; +--- vanilla-2.6.38.0.orig/net/sunrpc/sched.c ++++ vanilla-2.6.38.0/net/sunrpc/sched.c +@@ -637,14 +637,12 @@ static void __rpc_execute(struct rpc_tas + save_callback = task->tk_callback; + task->tk_callback = NULL; + save_callback(task); +- } +- +- /* +- * Perform the next FSM step. +- * tk_action may be NULL when the task has been killed +- * by someone else. +- */ +- if (!RPC_IS_QUEUED(task)) { ++ } else { ++ /* ++ * Perform the next FSM step. ++ * tk_action may be NULL when the task has been killed ++ * by someone else. ++ */ + if (task->tk_action == NULL) + break; + task->tk_action(task); +--- vanilla-2.6.38.0.orig/net/sunrpc/clnt.c ++++ vanilla-2.6.38.0/net/sunrpc/clnt.c +@@ -436,7 +436,9 @@ void rpc_killall_tasks(struct rpc_clnt * + if (!(rovr->tk_flags & RPC_TASK_KILLED)) { + rovr->tk_flags |= RPC_TASK_KILLED; + rpc_exit(rovr, -EIO); +- rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr); ++ if (RPC_IS_QUEUED(rovr)) ++ rpc_wake_up_queued_task(rovr->tk_waitqueue, ++ rovr); + } + } + spin_unlock(&clnt->cl_lock); +--- vanilla-2.6.38.0.orig/kernel/perf_event.c ++++ vanilla-2.6.38.0/kernel/perf_event.c +@@ -4567,7 +4567,7 @@ static int perf_exclude_event(struct per + struct pt_regs *regs) + { + if (event->hw.state & PERF_HES_STOPPED) +- return 0; ++ return 1; + + if (regs) { + if (event->attr.exclude_user && user_mode(regs)) +@@ -4923,6 +4923,8 @@ static int perf_tp_event_match(struct pe + struct perf_sample_data *data, + struct pt_regs *regs) + { ++ if (event->hw.state & PERF_HES_STOPPED) ++ return 0; + /* + * All tracepoints are from kernel-space. + */ +--- vanilla-2.6.38.0.orig/arch/powerpc/include/asm/reg.h ++++ vanilla-2.6.38.0/arch/powerpc/include/asm/reg.h +@@ -880,6 +880,7 @@ + #define PV_970 0x0039 + #define PV_POWER5 0x003A + #define PV_POWER5p 0x003B ++#define PV_POWER7 0x003F + #define PV_970FX 0x003C + #define PV_630 0x0040 + #define PV_630p 0x0041 +--- vanilla-2.6.38.0.orig/arch/powerpc/kernel/perf_event.c ++++ vanilla-2.6.38.0/arch/powerpc/kernel/perf_event.c +@@ -1269,6 +1269,28 @@ unsigned long perf_instruction_pointer(s + return ip; + } + ++static bool pmc_overflow(unsigned long val) ++{ ++ if ((int)val < 0) ++ return true; ++ ++ /* ++ * Events on POWER7 can roll back if a speculative event doesn't ++ * eventually complete. Unfortunately in some rare cases they will ++ * raise a performance monitor exception. We need to catch this to ++ * ensure we reset the PMC. In all cases the PMC will be 256 or less ++ * cycles from overflow. ++ * ++ * We only do this if the first pass fails to find any overflowing ++ * PMCs because a user might set a period of less than 256 and we ++ * don't want to mistakenly reset them. ++ */ ++ if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) ++ return true; ++ ++ return false; ++} ++ + /* + * Performance monitor interrupt stuff + */ +@@ -1316,7 +1338,7 @@ static void perf_event_interrupt(struct + if (is_limited_pmc(i + 1)) + continue; + val = read_pmc(i + 1); +- if ((int)val < 0) ++ if (pmc_overflow(val)) + write_pmc(i + 1, 0); + } + } +--- vanilla-2.6.38.0.orig/tools/perf/util/PERF-VERSION-GEN ++++ vanilla-2.6.38.0/tools/perf/util/PERF-VERSION-GEN +@@ -23,10 +23,10 @@ if test -d ../../.git -o -f ../../.git & + then + VN=$(echo "$VN" | sed -e 's/-/./g'); + else +- eval `grep '^VERSION\s*=' ../../Makefile|tr -d ' '` +- eval `grep '^PATCHLEVEL\s*=' ../../Makefile|tr -d ' '` +- eval `grep '^SUBLEVEL\s*=' ../../Makefile|tr -d ' '` +- eval `grep '^EXTRAVERSION\s*=' ../../Makefile|tr -d ' '` ++ eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ') ++ eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') ++ eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') ++ eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ') + + VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}" + fi +--- vanilla-2.6.38.0.orig/fs/ext3/namei.c ++++ vanilla-2.6.38.0/fs/ext3/namei.c +@@ -1540,8 +1540,8 @@ static int ext3_dx_add_entry(handle_t *h + goto cleanup; + node2 = (struct dx_node *)(bh2->b_data); + entries2 = node2->entries; ++ memset(&node2->fake, 0, sizeof(struct fake_dirent)); + node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize); +- node2->fake.inode = 0; + BUFFER_TRACE(frame->bh, "get_write_access"); + err = ext3_journal_get_write_access(handle, frame->bh); + if (err) +--- vanilla-2.6.38.0.orig/kernel/smp.c ++++ vanilla-2.6.38.0/kernel/smp.c +@@ -450,7 +450,7 @@ void smp_call_function_many(const struct + { + struct call_function_data *data; + unsigned long flags; +- int cpu, next_cpu, this_cpu = smp_processor_id(); ++ int refs, cpu, next_cpu, this_cpu = smp_processor_id(); + + /* + * Can deadlock when called with interrupts disabled. +@@ -461,7 +461,7 @@ void smp_call_function_many(const struct + WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled() + && !oops_in_progress && !early_boot_irqs_disabled); + +- /* So, what's a CPU they want? Ignoring this one. */ ++ /* Try to fastpath. So, what's a CPU they want? Ignoring this one. */ + cpu = cpumask_first_and(mask, cpu_online_mask); + if (cpu == this_cpu) + cpu = cpumask_next_and(cpu, mask, cpu_online_mask); +@@ -483,22 +483,49 @@ void smp_call_function_many(const struct + + data = &__get_cpu_var(cfd_data); + csd_lock(&data->csd); ++ ++ /* This BUG_ON verifies our reuse assertions and can be removed */ + BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask)); + ++ /* ++ * The global call function queue list add and delete are protected ++ * by a lock, but the list is traversed without any lock, relying ++ * on the rcu list add and delete to allow safe concurrent traversal. ++ * We reuse the call function data without waiting for any grace ++ * period after some other cpu removes it from the global queue. ++ * This means a cpu might find our data block as it is being ++ * filled out. ++ * ++ * We hold off the interrupt handler on the other cpu by ++ * ordering our writes to the cpu mask vs our setting of the ++ * refs counter. We assert only the cpu owning the data block ++ * will set a bit in cpumask, and each bit will only be cleared ++ * by the subject cpu. Each cpu must first find its bit is ++ * set and then check that refs is set indicating the element is ++ * ready to be processed, otherwise it must skip the entry. ++ * ++ * On the previous iteration refs was set to 0 by another cpu. ++ * To avoid the use of transitivity, set the counter to 0 here ++ * so the wmb will pair with the rmb in the interrupt handler. ++ */ ++ atomic_set(&data->refs, 0); /* convert 3rd to 1st party write */ ++ + data->csd.func = func; + data->csd.info = info; +- cpumask_and(data->cpumask, mask, cpu_online_mask); +- cpumask_clear_cpu(this_cpu, data->cpumask); + +- /* +- * To ensure the interrupt handler gets an complete view +- * we order the cpumask and refs writes and order the read +- * of them in the interrupt handler. In addition we may +- * only clear our own cpu bit from the mask. +- */ ++ /* Ensure 0 refs is visible before mask. Also orders func and info */ + smp_wmb(); + +- atomic_set(&data->refs, cpumask_weight(data->cpumask)); ++ /* We rely on the "and" being processed before the store */ ++ cpumask_and(data->cpumask, mask, cpu_online_mask); ++ cpumask_clear_cpu(this_cpu, data->cpumask); ++ refs = cpumask_weight(data->cpumask); ++ ++ /* Some callers race with other cpus changing the passed mask */ ++ if (unlikely(!refs)) { ++ csd_unlock(&data->csd); ++ return; ++ } + + raw_spin_lock_irqsave(&call_function.lock, flags); + /* +@@ -507,6 +534,12 @@ void smp_call_function_many(const struct + * will not miss any other list entries: + */ + list_add_rcu(&data->csd.list, &call_function.queue); ++ /* ++ * We rely on the wmb() in list_add_rcu to complete our writes ++ * to the cpumask before this write to refs, which indicates ++ * data is on the list and is ready to be processed. ++ */ ++ atomic_set(&data->refs, refs); + raw_spin_unlock_irqrestore(&call_function.lock, flags); + + /* +--- vanilla-2.6.38.0.orig/arch/x86/include/asm/pgtable-3level.h ++++ vanilla-2.6.38.0/arch/x86/include/asm/pgtable-3level.h +@@ -69,8 +69,6 @@ static inline void native_pmd_clear(pmd_ + + static inline void pud_clear(pud_t *pudp) + { +- unsigned long pgd; +- + set_pud(pudp, __pud(0)); + + /* +@@ -79,13 +77,10 @@ static inline void pud_clear(pud_t *pudp + * section 8.1: in PAE mode we explicitly have to flush the + * TLB via cr3 if the top-level pgd is changed... + * +- * Make sure the pud entry we're updating is within the +- * current pgd to avoid unnecessary TLB flushes. ++ * Currently all places where pud_clear() is called either have ++ * flush_tlb_mm() followed or don't need TLB flush (x86_64 code or ++ * pud_clear_bad()), so we don't need TLB flush here. + */ +- pgd = read_cr3(); +- if (__pa(pudp) >= pgd && __pa(pudp) < +- (pgd + sizeof(pgd_t)*PTRS_PER_PGD)) +- write_cr3(pgd); + } + + #ifdef CONFIG_SMP +--- vanilla-2.6.38.0.orig/arch/x86/mm/pgtable.c ++++ vanilla-2.6.38.0/arch/x86/mm/pgtable.c +@@ -168,8 +168,7 @@ void pud_populate(struct mm_struct *mm, + * section 8.1: in PAE mode we explicitly have to flush the + * TLB via cr3 if the top-level pgd is changed... + */ +- if (mm == current->active_mm) +- write_cr3(read_cr3()); ++ flush_tlb_mm(mm); + } + #else /* !CONFIG_X86_PAE */ + +--- vanilla-2.6.38.0.orig/drivers/hid/Makefile ++++ vanilla-2.6.38.0/drivers/hid/Makefile +@@ -27,7 +27,7 @@ endif + + obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o + obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o +-obj-$(CONFIG_HID_ACRUX_FF) += hid-axff.o ++obj-$(CONFIG_HID_ACRUX) += hid-axff.o + obj-$(CONFIG_HID_APPLE) += hid-apple.o + obj-$(CONFIG_HID_BELKIN) += hid-belkin.o + obj-$(CONFIG_HID_CANDO) += hid-cando.o +--- vanilla-2.6.38.0.orig/drivers/hid/hid-axff.c ++++ vanilla-2.6.38.0/drivers/hid/hid-axff.c +@@ -33,6 +33,8 @@ + #include + + #include "hid-ids.h" ++ ++#ifdef CONFIG_HID_ACRUX_FF + #include "usbhid/usbhid.h" + + struct axff_device { +@@ -109,6 +111,12 @@ err_free_mem: + kfree(axff); + return error; + } ++#else ++static inline int axff_init(struct hid_device *hid) ++{ ++ return 0; ++} ++#endif + + static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) + { +@@ -139,9 +147,25 @@ static int ax_probe(struct hid_device *h + error); + } + ++ /* ++ * We need to start polling device right away, otherwise ++ * it will go into a coma. ++ */ ++ error = hid_hw_open(hdev); ++ if (error) { ++ dev_err(&hdev->dev, "hw open failed\n"); ++ return error; ++ } ++ + return 0; + } + ++static void ax_remove(struct hid_device *hdev) ++{ ++ hid_hw_close(hdev); ++ hid_hw_stop(hdev); ++} ++ + static const struct hid_device_id ax_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, + { } +@@ -149,9 +173,10 @@ static const struct hid_device_id ax_dev + MODULE_DEVICE_TABLE(hid, ax_devices); + + static struct hid_driver ax_driver = { +- .name = "acrux", +- .id_table = ax_devices, +- .probe = ax_probe, ++ .name = "acrux", ++ .id_table = ax_devices, ++ .probe = ax_probe, ++ .remove = ax_remove, + }; + + static int __init ax_init(void) +--- vanilla-2.6.38.0.orig/drivers/hid/hid-input.c ++++ vanilla-2.6.38.0/drivers/hid/hid-input.c +@@ -290,14 +290,6 @@ static void hidinput_configure_usage(str + goto ignore; + } + +- if (field->report_type == HID_FEATURE_REPORT) { +- if (device->driver->feature_mapping) { +- device->driver->feature_mapping(device, hidinput, field, +- usage); +- } +- goto ignore; +- } +- + if (device->driver->input_mapping) { + int ret = device->driver->input_mapping(device, hidinput, field, + usage, &bit, &max); +@@ -835,6 +827,24 @@ static void hidinput_close(struct input_ + hid_hw_close(hid); + } + ++static void report_features(struct hid_device *hid) ++{ ++ struct hid_driver *drv = hid->driver; ++ struct hid_report_enum *rep_enum; ++ struct hid_report *rep; ++ int i, j; ++ ++ if (!drv->feature_mapping) ++ return; ++ ++ rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; ++ list_for_each_entry(rep, &rep_enum->report_list, list) ++ for (i = 0; i < rep->maxfield; i++) ++ for (j = 0; j < rep->field[i]->maxusage; j++) ++ drv->feature_mapping(hid, rep->field[i], ++ rep->field[i]->usage + j); ++} ++ + /* + * Register the input device; print a message. + * Configure the input layer interface +@@ -863,7 +873,9 @@ int hidinput_connect(struct hid_device * + return -1; + } + +- for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) { ++ report_features(hid); ++ ++ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { + if (k == HID_OUTPUT_REPORT && + hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) + continue; +--- vanilla-2.6.38.0.orig/drivers/hid/hid-multitouch.c ++++ vanilla-2.6.38.0/drivers/hid/hid-multitouch.c +@@ -122,7 +122,7 @@ struct mt_class mt_classes[] = { + { } + }; + +-static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi, ++static void mt_feature_mapping(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage) + { + if (usage->hid == HID_DG_INPUTMODE) { +--- vanilla-2.6.38.0.orig/include/linux/hid.h ++++ vanilla-2.6.38.0/include/linux/hid.h +@@ -638,7 +638,7 @@ struct hid_driver { + struct hid_input *hidinput, struct hid_field *field, + struct hid_usage *usage, unsigned long **bit, int *max); + void (*feature_mapping)(struct hid_device *hdev, +- struct hid_input *hidinput, struct hid_field *field, ++ struct hid_field *field, + struct hid_usage *usage); + #ifdef CONFIG_PM + int (*suspend)(struct hid_device *hdev, pm_message_t message); +--- vanilla-2.6.38.0.orig/arch/parisc/kernel/irq.c ++++ vanilla-2.6.38.0/arch/parisc/kernel/irq.c +@@ -108,7 +108,7 @@ int cpu_check_affinity(unsigned int irq, + int cpu_dest; + + /* timer and ipi have to always be received on all CPUs */ +- if (CHECK_IRQ_PER_CPU(irq)) { ++ if (CHECK_IRQ_PER_CPU(irq_to_desc(irq)->status)) { + /* Bad linux design decision. The mask has already + * been set; we must reset it */ + cpumask_setall(irq_desc[irq].affinity); +--- vanilla-2.6.38.0.orig/drivers/hid/hid-apple.c ++++ vanilla-2.6.38.0/drivers/hid/hid-apple.c +@@ -481,6 +481,12 @@ static const struct hid_device_id apple_ + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), ++ .driver_data = APPLE_HAS_FN }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), ++ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), ++ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), +--- vanilla-2.6.38.0.orig/drivers/input/mouse/bcm5974.c ++++ vanilla-2.6.38.0/drivers/input/mouse/bcm5974.c +@@ -63,6 +63,10 @@ + #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 + #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 + #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 ++/* Macbook8 (unibody, March 2011) */ ++#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 ++#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 ++#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 + + #define BCM5974_DEVICE(prod) { \ + .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ +@@ -96,6 +100,10 @@ static const struct usb_device_id bcm597 + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), ++ /* MacbookPro8 */ ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), ++ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), + /* Terminating entry */ + {} + }; +@@ -274,6 +282,18 @@ static const struct bcm5974_config bcm59 + { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, + { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } + }, ++ { ++ USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, ++ USB_DEVICE_ID_APPLE_WELLSPRING5_ISO, ++ USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, ++ HAS_INTEGRATED_BUTTON, ++ 0x84, sizeof(struct bt_data), ++ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, ++ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, ++ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, ++ { DIM_X, DIM_X / SN_COORD, -4415, 5050 }, ++ { DIM_Y, DIM_Y / SN_COORD, -55, 6680 } ++ }, + {} + }; + +--- vanilla-2.6.38.0.orig/Documentation/i2c/instantiating-devices ++++ vanilla-2.6.38.0/Documentation/i2c/instantiating-devices +@@ -100,7 +100,7 @@ static int __devinit usb_hcd_pnx4008_pro + (...) + i2c_adap = i2c_get_adapter(2); + memset(&i2c_info, 0, sizeof(struct i2c_board_info)); +- strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); ++ strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); + isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, + normal_i2c, NULL); + i2c_put_adapter(i2c_adap); +--- vanilla-2.6.38.0.orig/drivers/mmc/host/sdhci-pci.c ++++ vanilla-2.6.38.0/drivers/mmc/host/sdhci-pci.c +@@ -547,6 +547,14 @@ static const struct pci_device_id pci_id + }, + + { ++ .vendor = PCI_VENDOR_ID_RICOH, ++ .device = 0xe823, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = PCI_ANY_ID, ++ .driver_data = (kernel_ulong_t)&sdhci_ricoh_mmc, ++ }, ++ ++ { + .vendor = PCI_VENDOR_ID_ENE, + .device = PCI_DEVICE_ID_ENE_CB712_SD, + .subvendor = PCI_ANY_ID, +--- vanilla-2.6.38.0.orig/drivers/mmc/core/sdio.c ++++ vanilla-2.6.38.0/drivers/mmc/core/sdio.c +@@ -395,6 +395,14 @@ static int mmc_sdio_init_card(struct mmc + if (err) + goto remove; + ++ /* ++ * Update oldcard with the new RCA received from the SDIO ++ * device -- we're doing this so that it's updated in the ++ * "card" struct when oldcard overwrites that later. ++ */ ++ if (oldcard) ++ oldcard->rca = card->rca; ++ + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); + } + +--- vanilla-2.6.38.0.orig/arch/x86/kernel/entry_64.S ++++ vanilla-2.6.38.0/arch/x86/kernel/entry_64.S +@@ -1248,7 +1248,7 @@ ENTRY(xen_do_hypervisor_callback) # do + decl PER_CPU_VAR(irq_count) + jmp error_exit + CFI_ENDPROC +-END(do_hypervisor_callback) ++END(xen_do_hypervisor_callback) + + /* + * Hypervisor uses this for application faults while it executes. +--- vanilla-2.6.38.0.orig/arch/arm/mach-davinci/board-dm644x-evm.c ++++ vanilla-2.6.38.0/arch/arm/mach-davinci/board-dm644x-evm.c +@@ -440,11 +440,6 @@ evm_u35_setup(struct i2c_client *client, + gpio_request(gpio + 7, "nCF_SEL"); + gpio_direction_output(gpio + 7, 1); + +- /* irlml6401 switches over 1A, in under 8 msec; +- * now it can be managed by nDRV_VBUS ... +- */ +- davinci_setup_usb(1000, 8); +- + return 0; + } + +@@ -705,6 +700,9 @@ static __init void davinci_evm_init(void + davinci_serial_init(&uart_config); + dm644x_init_asp(&dm644x_evm_snd_data); + ++ /* irlml6401 switches over 1A, in under 8 msec */ ++ davinci_setup_usb(1000, 8); ++ + soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID; + /* Register the fixup for PHY on DaVinci */ + phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, +--- vanilla-2.6.38.0.orig/drivers/hwmon/sht15.c ++++ vanilla-2.6.38.0/drivers/hwmon/sht15.c +@@ -333,11 +333,11 @@ static inline int sht15_calc_humid(struc + + const int c1 = -4; + const int c2 = 40500; /* x 10 ^ -6 */ +- const int c3 = -2800; /* x10 ^ -9 */ ++ const int c3 = -28; /* x 10 ^ -7 */ + + RHlinear = c1*1000 + + c2 * data->val_humid/1000 +- + (data->val_humid * data->val_humid * c3)/1000000; ++ + (data->val_humid * data->val_humid * c3) / 10000; + return (temp - 25000) * (10000 + 80 * data->val_humid) + / 1000000 + RHlinear; + } diff --git a/kernel.spec b/kernel.spec index 25ae1f8ef..8266f6b86 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1350,7 +1350,7 @@ ApplyPatch efifb_update.patch ApplyPatch acpi_reboot.patch # Runtime PM -ApplyPatch linux-2.6-ehci-check-port-status.patch +#ApplyPatch linux-2.6-ehci-check-port-status.patch #ApplyPatch linux-2.6-usb-pci-autosuspend.patch ### Broken by implicit notify support & ACPICA rebase ###ApplyPatch linux-2.6-enable-more-pci-autosuspend.patch @@ -1970,6 +1970,9 @@ fi # and build. %changelog +* Mon Mar 21 2011 Chuck Ebbert 2.6.38-3 +- Add contents of 2.6.38.1 patch queue (in git-linus.diff) + * Thu Mar 17 2011 Matthew Garrett 2.6.38-2 - drop efi_default_physical.patch - it's actually setting up something that's neither physical nor virtual, and it's probably breaking EFI boots From 1abc8547061e0da302dd6ae1f2d71e8c2916765d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 22 Mar 2011 19:30:11 +1000 Subject: [PATCH 04/99] nouveau: s/r fix for rhbz#688569 --- drm-nouveau-updates.patch | 238 +++++++++++++++++++++++++++++++++----- kernel.spec | 6 +- 2 files changed, 211 insertions(+), 33 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 3bd652fa6..90a716dba 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,21 +1,24 @@ - drivers/gpu/drm/nouveau/nouveau_bios.c | 25 +-- + drivers/gpu/drm/nouveau/nouveau_bios.c | 78 +++++-- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 +- drivers/gpu/drm/nouveau/nouveau_channel.c | 2 +- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 2 - drivers/gpu/drm/nouveau/nouveau_drv.h | 15 +- - drivers/gpu/drm/nouveau/nouveau_fence.c | 190 ++++++++++------ + drivers/gpu/drm/nouveau/nouveau_fence.c | 205 +++++++++++------ drivers/gpu/drm/nouveau/nouveau_mem.c | 50 +++- drivers/gpu/drm/nouveau/nouveau_object.c | 22 ++- + drivers/gpu/drm/nouveau/nouveau_perf.c | 2 +- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 341 +++++++++++++++++++++++++---- drivers/gpu/drm/nouveau/nouveau_state.c | 10 +- drivers/gpu/drm/nouveau/nouveau_temp.c | 4 +- drivers/gpu/drm/nouveau/nouveau_util.c | 23 ++- drivers/gpu/drm/nouveau/nouveau_util.h | 4 + drivers/gpu/drm/nouveau/nouveau_vm.c | 13 +- + drivers/gpu/drm/nouveau/nv04_dfp.c | 13 +- drivers/gpu/drm/nouveau/nv04_fifo.c | 19 ++- drivers/gpu/drm/nouveau/nv40_fb.c | 59 +++++- drivers/gpu/drm/nouveau/nv50_display.c | 7 +- + drivers/gpu/drm/nouveau/nv50_evo.c | 1 + drivers/gpu/drm/nouveau/nv50_fb.c | 150 ++++++++++++- drivers/gpu/drm/nouveau/nv50_fifo.c | 3 +- drivers/gpu/drm/nouveau/nv50_gpio.c | 13 +- @@ -24,13 +27,68 @@ drivers/gpu/drm/nouveau/nv84_crypt.c | 2 +- drivers/gpu/drm/nouveau/nvc0_fifo.c | 15 +- drivers/gpu/drm/nouveau/nvc0_graph.c | 2 - - 26 files changed, 841 insertions(+), 281 deletions(-) + 29 files changed, 912 insertions(+), 294 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c -index 6bdab89..b8ff1e7 100644 +index 6bdab89..1bb1261 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c -@@ -5950,6 +5950,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) +@@ -269,7 +269,7 @@ struct init_tbl_entry { + int (*handler)(struct nvbios *, uint16_t, struct init_exec *); + }; + +-static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *); ++static int parse_init_table(struct nvbios *, uint16_t, struct init_exec *); + + #define MACRO_INDEX_SIZE 2 + #define MACRO_SIZE 8 +@@ -2011,6 +2011,27 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + } + + static int ++init_jump(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ++{ ++ /* ++ * INIT_JUMP opcode: 0x5C ('\') ++ * ++ * offset (8 bit): opcode ++ * offset + 1 (16 bit): offset (in bios) ++ * ++ * Continue execution of init table from 'offset' ++ */ ++ ++ uint16_t jmp_offset = ROM16(bios->data[offset + 1]); ++ ++ if (!iexec->execute) ++ return 3; ++ ++ BIOSLOG(bios, "0x%04X: Jump to 0x%04X\n", offset, jmp_offset); ++ return jmp_offset - offset; ++} ++ ++static int + init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + { + /* +@@ -3659,6 +3680,7 @@ static struct init_tbl_entry itbl_entry[] = { + { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, + /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ + { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, ++ { "INIT_JUMP" , 0x5C, init_jump }, + { "INIT_I2C_IF" , 0x5E, init_i2c_if }, + { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, + { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, +@@ -3700,8 +3722,7 @@ static struct init_tbl_entry itbl_entry[] = { + #define MAX_TABLE_OPS 1000 + + static int +-parse_init_table(struct nvbios *bios, unsigned int offset, +- struct init_exec *iexec) ++parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + { + /* + * Parses all commands in an init table. +@@ -5950,6 +5971,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) } } @@ -42,7 +100,7 @@ index 6bdab89..b8ff1e7 100644 static void parse_dcb_connector_table(struct nvbios *bios) { -@@ -5986,23 +5991,9 @@ parse_dcb_connector_table(struct nvbios *bios) +@@ -5986,23 +6012,9 @@ parse_dcb_connector_table(struct nvbios *bios) cte->type = (cte->entry & 0x000000ff) >> 0; cte->index2 = (cte->entry & 0x00000f00) >> 8; @@ -69,6 +127,39 @@ index 6bdab89..b8ff1e7 100644 if (cte->type == 0xff) continue; +@@ -6342,6 +6354,32 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) + } + } + ++ /* XFX GT-240X-YA ++ * ++ * So many things wrong here, replace the entire encoder table.. ++ */ ++ if (nv_match_device(dev, 0x0ca3, 0x1682, 0x3003)) { ++ if (idx == 0) { ++ *conn = 0x02001300; /* VGA, connector 1 */ ++ *conf = 0x00000028; ++ } else ++ if (idx == 1) { ++ *conn = 0x01010312; /* DVI, connector 0 */ ++ *conf = 0x00020030; ++ } else ++ if (idx == 2) { ++ *conn = 0x01010310; /* VGA, connector 0 */ ++ *conf = 0x00000028; ++ } else ++ if (idx == 3) { ++ *conn = 0x02022362; /* HDMI, connector 2 */ ++ *conf = 0x00020010; ++ } else { ++ *conn = 0x0000000e; /* EOL */ ++ *conf = 0x00000000; ++ } ++ } ++ + return true; + } + diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index a521840..53a8000 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -185,10 +276,18 @@ index 982d70b..2cae8e7 100644 /* nvc0_fb.c */ extern int nvc0_fb_init(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c -index 221b846..8b46392 100644 +index 221b846..594911f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c -@@ -32,8 +32,7 @@ +@@ -27,13 +27,15 @@ + #include "drmP.h" + #include "drm.h" + ++#include ++#include ++ + #include "nouveau_drv.h" + #include "nouveau_ramht.h" #include "nouveau_dma.h" #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) @@ -198,7 +297,33 @@ index 221b846..8b46392 100644 struct nouveau_fence { struct nouveau_channel *channel; -@@ -259,11 +258,12 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) +@@ -230,7 +232,8 @@ int + __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) + { + unsigned long timeout = jiffies + (3 * DRM_HZ); +- unsigned long sleep_time = jiffies + 1; ++ unsigned long sleep_time = NSEC_PER_MSEC / 1000; ++ ktime_t t; + int ret = 0; + + while (1) { +@@ -244,8 +247,13 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) + + __set_current_state(intr ? TASK_INTERRUPTIBLE + : TASK_UNINTERRUPTIBLE); +- if (lazy && time_after_eq(jiffies, sleep_time)) +- schedule_timeout(1); ++ if (lazy) { ++ t = ktime_set(0, sleep_time); ++ schedule_hrtimeout(&t, HRTIMER_MODE_REL); ++ sleep_time *= 2; ++ if (sleep_time > NSEC_PER_MSEC) ++ sleep_time = NSEC_PER_MSEC; ++ } + + if (intr && signal_pending(current)) { + ret = -ERESTARTSYS; +@@ -259,11 +267,12 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) } static struct nouveau_semaphore * @@ -213,7 +338,7 @@ index 221b846..8b46392 100644 if (!USE_SEMA(dev)) return NULL; -@@ -277,9 +277,9 @@ alloc_semaphore(struct drm_device *dev) +@@ -277,9 +286,9 @@ alloc_semaphore(struct drm_device *dev) goto fail; spin_lock(&dev_priv->fence.lock); @@ -225,7 +350,7 @@ index 221b846..8b46392 100644 spin_unlock(&dev_priv->fence.lock); if (!sema->mem) -@@ -287,7 +287,8 @@ alloc_semaphore(struct drm_device *dev) +@@ -287,7 +296,8 @@ alloc_semaphore(struct drm_device *dev) kref_init(&sema->ref); sema->dev = dev; @@ -235,7 +360,7 @@ index 221b846..8b46392 100644 return sema; fail: -@@ -296,7 +297,7 @@ fail: +@@ -296,7 +306,7 @@ fail: } static void @@ -244,7 +369,7 @@ index 221b846..8b46392 100644 { struct nouveau_semaphore *sema = container_of(ref, struct nouveau_semaphore, ref); -@@ -318,61 +319,107 @@ semaphore_work(void *priv, bool signalled) +@@ -318,61 +328,107 @@ semaphore_work(void *priv, bool signalled) if (unlikely(!signalled)) nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1); @@ -360,6 +485,19 @@ index 221b846..8b46392 100644 + if (dev_priv->chipset < 0xc0) { + struct nouveau_vma *vma = &dev_priv->fence.bo->vma; + u64 offset = vma->offset + sema->mem->start; ++ ++ ret = RING_SPACE(chan, 5); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubSw, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ OUT_RING (chan, 1); ++ OUT_RING (chan, 2); /* RELEASE */ ++ } else { ++ struct nouveau_vma *vma = &dev_priv->fence.bo->vma; ++ u64 offset = vma->offset + sema->mem->start; - BEGIN_RING(chan, NvSubSw, method, 1); - OUT_RING(chan, 1); @@ -376,19 +514,6 @@ index 221b846..8b46392 100644 + if (ret) + return ret; + -+ BEGIN_RING(chan, NvSubSw, 0x0010, 4); -+ OUT_RING (chan, upper_32_bits(offset)); -+ OUT_RING (chan, lower_32_bits(offset)); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 2); /* RELEASE */ -+ } else { -+ struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -+ u64 offset = vma->offset + sema->mem->start; -+ -+ ret = RING_SPACE(chan, 5); -+ if (ret) -+ return ret; -+ + BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + OUT_RING (chan, upper_32_bits(offset)); + OUT_RING (chan, lower_32_bits(offset)); @@ -397,7 +522,7 @@ index 221b846..8b46392 100644 } /* Delay semaphore destruction until its work is done */ -@@ -383,7 +430,6 @@ emit_semaphore(struct nouveau_channel *chan, int method, +@@ -383,7 +439,6 @@ emit_semaphore(struct nouveau_channel *chan, int method, kref_get(&sema->ref); nouveau_fence_work(fence, semaphore_work, sema); nouveau_fence_unref(&fence); @@ -405,7 +530,7 @@ index 221b846..8b46392 100644 return 0; } -@@ -400,7 +446,7 @@ nouveau_fence_sync(struct nouveau_fence *fence, +@@ -400,7 +455,7 @@ nouveau_fence_sync(struct nouveau_fence *fence, nouveau_fence_signalled(fence))) goto out; @@ -414,7 +539,7 @@ index 221b846..8b46392 100644 if (!sema) { /* Early card or broken userspace, fall back to * software sync. */ -@@ -418,17 +464,17 @@ nouveau_fence_sync(struct nouveau_fence *fence, +@@ -418,17 +473,17 @@ nouveau_fence_sync(struct nouveau_fence *fence, } /* Make wchan wait until it gets signalled */ @@ -435,7 +560,7 @@ index 221b846..8b46392 100644 out: if (chan) nouveau_channel_put_unlocked(&chan); -@@ -449,22 +495,23 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) +@@ -449,22 +504,23 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) struct nouveau_gpuobj *obj = NULL; int ret; @@ -467,7 +592,7 @@ index 221b846..8b46392 100644 struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -@@ -484,14 +531,20 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) +@@ -484,14 +540,20 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) return ret; BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); OUT_RING(chan, NvSema); @@ -489,7 +614,7 @@ index 221b846..8b46392 100644 return 0; } -@@ -519,11 +572,12 @@ int +@@ -519,11 +581,12 @@ int nouveau_fence_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -606,6 +731,19 @@ index 30b6544..3c12461 100644 } } +diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c +index ac62a1b..670e3cb 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_perf.c ++++ b/drivers/gpu/drm/nouveau/nouveau_perf.c +@@ -134,7 +134,7 @@ nouveau_perf_init(struct drm_device *dev) + case 0x13: + case 0x15: + perflvl->fanspeed = entry[55]; +- perflvl->voltage = entry[56]; ++ perflvl->voltage = (recordlen > 56) ? entry[56] : 0; + perflvl->core = ROM32(entry[1]) * 10; + perflvl->memory = ROM32(entry[5]) * 20; + break; diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 9a250eb..a26383b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -1161,6 +1299,30 @@ index 97d82ae..b4658f7 100644 } else { kfree(vm); return -ENOSYS; +diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c +index c82db37..12098bf 100644 +--- a/drivers/gpu/drm/nouveau/nv04_dfp.c ++++ b/drivers/gpu/drm/nouveau/nv04_dfp.c +@@ -581,12 +581,13 @@ static void nv04_dfp_restore(struct drm_encoder *encoder) + int head = nv_encoder->restore.head; + + if (nv_encoder->dcb->type == OUTPUT_LVDS) { +- struct drm_display_mode *native_mode = nouveau_encoder_connector_get(nv_encoder)->native_mode; +- if (native_mode) +- call_lvds_script(dev, nv_encoder->dcb, head, LVDS_PANEL_ON, +- native_mode->clock); +- else +- NV_ERROR(dev, "Not restoring LVDS without native mode\n"); ++ struct nouveau_connector *connector = ++ nouveau_encoder_connector_get(nv_encoder); ++ ++ if (connector && connector->native_mode) ++ call_lvds_script(dev, nv_encoder->dcb, head, ++ LVDS_PANEL_ON, ++ connector->native_mode->clock); + + } else if (nv_encoder->dcb->type == OUTPUT_TMDS) { + int clock = nouveau_hw_pllvals_to_clk diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c index f89d104..db465a3 100644 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c @@ -1329,6 +1491,18 @@ index 7cc94ed..a804a35 100644 delayed |= clock; intr1 &= ~clock; } +diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c +index 0ea090f..3055dbe 100644 +--- a/drivers/gpu/drm/nouveau/nv50_evo.c ++++ b/drivers/gpu/drm/nouveau/nv50_evo.c +@@ -182,6 +182,7 @@ nv50_evo_channel_init(struct nouveau_channel *evo) + nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); + + evo->dma.max = (4096/4) - 2; ++ evo->dma.max &= ~7; + evo->dma.put = 0; + evo->dma.cur = evo->dma.put; + evo->dma.free = evo->dma.max - evo->dma.cur; diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c index 50290de..efc8cd4 100644 --- a/drivers/gpu/drm/nouveau/nv50_fb.c diff --git a/kernel.spec b/kernel.spec index 8266f6b86..201973982 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 3 +%global baserelease 4 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1970,6 +1970,10 @@ fi # and build. %changelog +* Tue Mar 22 2011 Ben Skeggs 2.6.38-4 +- nouveau: implement missing bios opcode 0x5c (rhbz#688569) +- nouveau: a couple of minor fixes from nouveau git + * Mon Mar 21 2011 Chuck Ebbert 2.6.38-3 - Add contents of 2.6.38.1 patch queue (in git-linus.diff) From e04a1dcc80bb7d476cd8f19463256a854322e18b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 23 Mar 2011 09:41:36 +1000 Subject: [PATCH 05/99] i915: add fix for 945G misrendering terminal --- drm-i915-fix-pipelined-fencing.patch | 80 ++++++++++++++++++++++++++++ kernel.spec | 8 ++- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 drm-i915-fix-pipelined-fencing.patch diff --git a/drm-i915-fix-pipelined-fencing.patch b/drm-i915-fix-pipelined-fencing.patch new file mode 100644 index 000000000..b6c016c54 --- /dev/null +++ b/drm-i915-fix-pipelined-fencing.patch @@ -0,0 +1,80 @@ +From 3b936797f5e4623ae1b80a5f0c4df30a17360bf5 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Thu, 17 Mar 2011 15:23:22 +0000 +Subject: [PATCH] drm/i915: Fix pipelined fencing + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=34584 +Cc: Andy Whitcroft +Cc: Daniel Vetter +Signed-off-by: Chris Wilson +--- + drivers/gpu/drm/i915/i915_gem.c | 46 ++++++++++++++++---------------------- + 1 files changed, 19 insertions(+), 27 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c +index 36e66cc..10378a3 100644 +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -2544,8 +2544,25 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, + reg = &dev_priv->fence_regs[obj->fence_reg]; + list_move_tail(®->lru_list, &dev_priv->mm.fence_list); + +- if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) +- pipelined = NULL; ++ if (obj->tiling_changed) { ++ ret = i915_gem_object_flush_fence(obj, ++ pipelined, ++ interruptible); ++ if (ret) ++ return ret; ++ ++ if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) ++ pipelined = NULL; ++ ++ if (pipelined) { ++ reg->setup_seqno = ++ i915_gem_next_request_seqno(dev, pipelined); ++ obj->last_fenced_seqno = reg->setup_seqno; ++ obj->last_fenced_ring = pipelined; ++ } ++ ++ goto update; ++ } + + if (!pipelined) { + if (reg->setup_seqno) { +@@ -2568,31 +2585,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, + interruptible); + if (ret) + return ret; +- } else if (obj->tiling_changed) { +- if (obj->fenced_gpu_access) { +- if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { +- ret = i915_gem_flush_ring(obj->base.dev, obj->ring, +- 0, obj->base.write_domain); +- if (ret) +- return ret; +- } +- +- obj->fenced_gpu_access = false; +- } +- } +- +- if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) +- pipelined = NULL; +- BUG_ON(!pipelined && reg->setup_seqno); +- +- if (obj->tiling_changed) { +- if (pipelined) { +- reg->setup_seqno = +- i915_gem_next_request_seqno(dev, pipelined); +- obj->last_fenced_seqno = reg->setup_seqno; +- obj->last_fenced_ring = pipelined; +- } +- goto update; + } + + return 0; +-- +1.5.6.5 + diff --git a/kernel.spec b/kernel.spec index 201973982..8dce0b1a0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 4 +%global baserelease 5 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -672,6 +672,8 @@ Patch1555: fix_xen_guest_on_old_EC2.patch Patch1810: drm-nouveau-updates.patch Patch1819: drm-intel-big-hammer.patch # intel drm is all merged upstream +# fix for 945G corruption will hit stable eventually +Patch1821: drm-i915-fix-pipelined-fencing.patch Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open Patch1825: drm-intel-make-lvds-work.patch @@ -1306,6 +1308,7 @@ ApplyPatch drm-intel-big-hammer.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch drm-intel-edp-fixes.patch +ApplyPatch drm-i915-fix-pipelined-fencing.patch # rhbz#681285 (i965: crash in brw_wm_surface_state.c::prepare_wm_surfaces() # where intelObj->mt == NULL) #ApplyPatch drm-i915-gen4-has-non-power-of-two-strides.patch @@ -1970,6 +1973,9 @@ fi # and build. %changelog +* Wed Mar 23 2011 Dave Airlie 2.6.38-5 +- i915: add fix for 945G misrendering terminal + * Tue Mar 22 2011 Ben Skeggs 2.6.38-4 - nouveau: implement missing bios opcode 0x5c (rhbz#688569) - nouveau: a couple of minor fixes from nouveau git From a13914ae1ea1d401e91b903e752649a9f1a5a339 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 23 Mar 2011 09:38:08 -0400 Subject: [PATCH 06/99] re-create ACPI battery sysfs files on resume from suspend Fixes the upstream changes to the dropped acpi-update-battery-information-on-notification-0x81.patch. --- ...e-sysfs-files-from-a-resume-notifier.patch | 89 +++++++++++++++++++ kernel.spec | 8 ++ 2 files changed, 97 insertions(+) create mode 100644 acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch diff --git a/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch b/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch new file mode 100644 index 000000000..b3256a2d3 --- /dev/null +++ b/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch @@ -0,0 +1,89 @@ +From lenb@kernel.org Wed Mar 23 03:07:45 2011 +From: Len Brown +To: linux-acpi@vger.kernel.org +Cc: Kyle McMartin , Len Brown +Subject: [PATCH 35/42] ACPI battery: fribble sysfs files from a resume notifier +Date: Wed, 23 Mar 2011 02:42:48 -0400 + +From: Kyle McMartin + +Commit da8aeb92 re-poked the battery on resume, but Linus reports that +it broke his eee and partially reverted it in b23fffd7. Unfortunately +this also results in my x201s giving crack values until the sysfs files +are poked again. In the revert message, it was suggested that we poke it +from a PM notifier, so let's do that. + +With this in place, I haven't noticed the units going nutty on my +gnome-power-manager across a dozen suspends or so... + +Signed-off-by: Kyle McMartin +Acked-by: Rafael J. Wysocki +Signed-off-by: Len Brown +--- + drivers/acpi/battery.c | 22 ++++++++++++++++++++++ + 1 files changed, 22 insertions(+), 0 deletions(-) + +diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c +index ac1a599..fcc13ac 100644 +--- a/drivers/acpi/battery.c ++++ b/drivers/acpi/battery.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_ACPI_PROCFS_POWER + #include +@@ -102,6 +103,7 @@ struct acpi_battery { + struct mutex lock; + struct power_supply bat; + struct acpi_device *device; ++ struct notifier_block pm_nb; + unsigned long update_time; + int rate_now; + int capacity_now; +@@ -940,6 +942,21 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event) + power_supply_changed(&battery->bat); + } + ++static int battery_notify(struct notifier_block *nb, ++ unsigned long mode, void *_unused) ++{ ++ struct acpi_battery *battery = container_of(nb, struct acpi_battery, ++ pm_nb); ++ switch (mode) { ++ case PM_POST_SUSPEND: ++ sysfs_remove_battery(battery); ++ sysfs_add_battery(battery); ++ break; ++ } ++ ++ return 0; ++} ++ + static int acpi_battery_add(struct acpi_device *device) + { + int result = 0; +@@ -972,6 +989,10 @@ static int acpi_battery_add(struct acpi_device *device) + #endif + kfree(battery); + } ++ ++ battery->pm_nb.notifier_call = battery_notify; ++ register_pm_notifier(&battery->pm_nb); ++ + return result; + } + +@@ -982,6 +1003,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) + if (!device || !acpi_driver_data(device)) + return -EINVAL; + battery = acpi_driver_data(device); ++ unregister_pm_notifier(&battery->pm_nb); + #ifdef CONFIG_ACPI_PROCFS_POWER + acpi_battery_remove_fs(device); + #endif +-- +1.7.4.1.343.ga91df + diff --git a/kernel.spec b/kernel.spec index 8dce0b1a0..e40bf2b2f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -642,6 +642,8 @@ Patch391: linux-2.6-acpi-video-dos.patch Patch393: acpi-ec-add-delay-before-write.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch +Patch399: acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch + Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch Patch454: thinkpad-acpi-fix-backlight.patch @@ -1226,6 +1228,7 @@ ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch ApplyPatch acpi-ec-add-delay-before-write.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch +ApplyPatch acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-sizeof-structs.patch @@ -1973,6 +1976,11 @@ fi # and build. %changelog +* Wed Mar 23 2011 Kyle McMartin +- Re-create ACPI battery sysfs files on resume from suspend, fixes the + upstream changes to the dropped + acpi-update-battery-information-on-notification-0x81.patch. + * Wed Mar 23 2011 Dave Airlie 2.6.38-5 - i915: add fix for 945G misrendering terminal From 6236c85dc675d8c7defbf2e34a865aa28e9c0594 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 23 Mar 2011 17:50:28 -0400 Subject: [PATCH 07/99] Linux 2.6.38.1 Drop linux-2.6-ehci-check-port-status.patch, merged in .38.1 Add dcdbas-force-smi-to-happen-when-expected.patch --- ...as-force-smi-to-happen-when-expected.patch | 34 + git-linus.diff | 2604 ----------------- kernel.spec | 17 +- linux-2.6-ehci-check-port-status.patch | 54 - sources | 1 + 5 files changed, 48 insertions(+), 2662 deletions(-) create mode 100644 dcdbas-force-smi-to-happen-when-expected.patch delete mode 100644 linux-2.6-ehci-check-port-status.patch diff --git a/dcdbas-force-smi-to-happen-when-expected.patch b/dcdbas-force-smi-to-happen-when-expected.patch new file mode 100644 index 000000000..a7a2c8a36 --- /dev/null +++ b/dcdbas-force-smi-to-happen-when-expected.patch @@ -0,0 +1,34 @@ +From: Stuart Hayes +Date: Wed, 2 Mar 2011 12:42:05 +0000 (+0100) +Subject: dcdbas: force SMI to happen when expected +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=dd65c736d1b5312c80c88a64bf521db4959eded5 + +dcdbas: force SMI to happen when expected + +The dcdbas driver can do an I/O write to cause a SMI to occur. The SMI handler +looks at certain registers and memory locations, so the SMI needs to happen +immediately. On some systems I/O writes are posted, though, causing the SMI to +happen well after the "outb" occurred, which causes random failures. Following +the "outb" with an "inb" forces the write to go through even if it is posted. + +Signed-off-by: Stuart Hayes +Acked-by: Doug Warzecha +Signed-off-by: Jiri Kosina +--- + +diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c +index 69ad529..ea5ac2d 100644 +--- a/drivers/firmware/dcdbas.c ++++ b/drivers/firmware/dcdbas.c +@@ -268,8 +268,10 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd) + } + + /* generate SMI */ ++ /* inb to force posted write through and make SMI happen now */ + asm volatile ( +- "outb %b0,%w1" ++ "outb %b0,%w1\n" ++ "inb %w1" + : /* no output args */ + : "a" (smi_cmd->command_code), + "d" (smi_cmd->command_address), diff --git a/git-linus.diff b/git-linus.diff index 4e0798a9e..e69de29bb 100644 --- a/git-linus.diff +++ b/git-linus.diff @@ -1,2604 +0,0 @@ ---- vanilla-2.6.38.0.orig/fs/dcache.c -+++ vanilla-2.6.38.0/fs/dcache.c -@@ -296,8 +296,12 @@ static struct dentry *d_kill(struct dent - __releases(parent->d_lock) - __releases(dentry->d_inode->i_lock) - { -- dentry->d_parent = NULL; - list_del(&dentry->d_u.d_child); -+ /* -+ * Inform try_to_ascend() that we are no longer attached to the -+ * dentry tree -+ */ -+ dentry->d_flags |= DCACHE_DISCONNECTED; - if (parent) - spin_unlock(&parent->d_lock); - dentry_iput(dentry); -@@ -1012,6 +1016,35 @@ void shrink_dcache_for_umount(struct sup - } - - /* -+ * This tries to ascend one level of parenthood, but -+ * we can race with renaming, so we need to re-check -+ * the parenthood after dropping the lock and check -+ * that the sequence number still matches. -+ */ -+static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq) -+{ -+ struct dentry *new = old->d_parent; -+ -+ rcu_read_lock(); -+ spin_unlock(&old->d_lock); -+ spin_lock(&new->d_lock); -+ -+ /* -+ * might go back up the wrong parent if we have had a rename -+ * or deletion -+ */ -+ if (new != old->d_parent || -+ (old->d_flags & DCACHE_DISCONNECTED) || -+ (!locked && read_seqretry(&rename_lock, seq))) { -+ spin_unlock(&new->d_lock); -+ new = NULL; -+ } -+ rcu_read_unlock(); -+ return new; -+} -+ -+ -+/* - * Search for at least 1 mount point in the dentry's subdirs. - * We descend to the next level whenever the d_subdirs - * list is non-empty and continue searching. -@@ -1066,24 +1099,10 @@ resume: - * All done at this level ... ascend and resume the search. - */ - if (this_parent != parent) { -- struct dentry *tmp; -- struct dentry *child; -- -- tmp = this_parent->d_parent; -- rcu_read_lock(); -- spin_unlock(&this_parent->d_lock); -- child = this_parent; -- this_parent = tmp; -- spin_lock(&this_parent->d_lock); -- /* might go back up the wrong parent if we have had a rename -- * or deletion */ -- if (this_parent != child->d_parent || -- (!locked && read_seqretry(&rename_lock, seq))) { -- spin_unlock(&this_parent->d_lock); -- rcu_read_unlock(); -+ struct dentry *child = this_parent; -+ this_parent = try_to_ascend(this_parent, locked, seq); -+ if (!this_parent) - goto rename_retry; -- } -- rcu_read_unlock(); - next = child->d_u.d_child.next; - goto resume; - } -@@ -1181,24 +1200,10 @@ resume: - * All done at this level ... ascend and resume the search. - */ - if (this_parent != parent) { -- struct dentry *tmp; -- struct dentry *child; -- -- tmp = this_parent->d_parent; -- rcu_read_lock(); -- spin_unlock(&this_parent->d_lock); -- child = this_parent; -- this_parent = tmp; -- spin_lock(&this_parent->d_lock); -- /* might go back up the wrong parent if we have had a rename -- * or deletion */ -- if (this_parent != child->d_parent || -- (!locked && read_seqretry(&rename_lock, seq))) { -- spin_unlock(&this_parent->d_lock); -- rcu_read_unlock(); -+ struct dentry *child = this_parent; -+ this_parent = try_to_ascend(this_parent, locked, seq); -+ if (!this_parent) - goto rename_retry; -- } -- rcu_read_unlock(); - next = child->d_u.d_child.next; - goto resume; - } -@@ -2942,28 +2947,14 @@ resume: - spin_unlock(&dentry->d_lock); - } - if (this_parent != root) { -- struct dentry *tmp; -- struct dentry *child; -- -- tmp = this_parent->d_parent; -+ struct dentry *child = this_parent; - if (!(this_parent->d_flags & DCACHE_GENOCIDE)) { - this_parent->d_flags |= DCACHE_GENOCIDE; - this_parent->d_count--; - } -- rcu_read_lock(); -- spin_unlock(&this_parent->d_lock); -- child = this_parent; -- this_parent = tmp; -- spin_lock(&this_parent->d_lock); -- /* might go back up the wrong parent if we have had a rename -- * or deletion */ -- if (this_parent != child->d_parent || -- (!locked && read_seqretry(&rename_lock, seq))) { -- spin_unlock(&this_parent->d_lock); -- rcu_read_unlock(); -+ this_parent = try_to_ascend(this_parent, locked, seq); -+ if (!this_parent) - goto rename_retry; -- } -- rcu_read_unlock(); - next = child->d_u.d_child.next; - goto resume; - } ---- vanilla-2.6.38.0.orig/include/linux/ftrace.h -+++ vanilla-2.6.38.0/include/linux/ftrace.h -@@ -428,6 +428,7 @@ extern void unregister_ftrace_graph(void - - extern void ftrace_graph_init_task(struct task_struct *t); - extern void ftrace_graph_exit_task(struct task_struct *t); -+extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu); - - static inline int task_curr_ret_stack(struct task_struct *t) - { -@@ -451,6 +452,7 @@ static inline void unpause_graph_tracing - - static inline void ftrace_graph_init_task(struct task_struct *t) { } - static inline void ftrace_graph_exit_task(struct task_struct *t) { } -+static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { } - - static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc, - trace_func_graph_ent_t entryfunc) ---- vanilla-2.6.38.0.orig/kernel/sched.c -+++ vanilla-2.6.38.0/kernel/sched.c -@@ -5572,7 +5572,7 @@ void __cpuinit init_idle(struct task_str - * The idle tasks have their own, simple scheduling class: - */ - idle->sched_class = &idle_sched_class; -- ftrace_graph_init_task(idle); -+ ftrace_graph_init_idle_task(idle, cpu); - } - - /* ---- vanilla-2.6.38.0.orig/kernel/trace/ftrace.c -+++ vanilla-2.6.38.0/kernel/trace/ftrace.c -@@ -3328,7 +3328,7 @@ static int start_graph_tracing(void) - /* The cpu_boot init_task->ret_stack will never be freed */ - for_each_online_cpu(cpu) { - if (!idle_task(cpu)->ret_stack) -- ftrace_graph_init_task(idle_task(cpu)); -+ ftrace_graph_init_idle_task(idle_task(cpu), cpu); - } - - do { -@@ -3418,6 +3418,49 @@ void unregister_ftrace_graph(void) - mutex_unlock(&ftrace_lock); - } - -+static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); -+ -+static void -+graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) -+{ -+ atomic_set(&t->tracing_graph_pause, 0); -+ atomic_set(&t->trace_overrun, 0); -+ t->ftrace_timestamp = 0; -+ /* make curr_ret_stack visable before we add the ret_stack */ -+ smp_wmb(); -+ t->ret_stack = ret_stack; -+} -+ -+/* -+ * Allocate a return stack for the idle task. May be the first -+ * time through, or it may be done by CPU hotplug online. -+ */ -+void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) -+{ -+ t->curr_ret_stack = -1; -+ /* -+ * The idle task has no parent, it either has its own -+ * stack or no stack at all. -+ */ -+ if (t->ret_stack) -+ WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu)); -+ -+ if (ftrace_graph_active) { -+ struct ftrace_ret_stack *ret_stack; -+ -+ ret_stack = per_cpu(idle_ret_stack, cpu); -+ if (!ret_stack) { -+ ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH -+ * sizeof(struct ftrace_ret_stack), -+ GFP_KERNEL); -+ if (!ret_stack) -+ return; -+ per_cpu(idle_ret_stack, cpu) = ret_stack; -+ } -+ graph_init_task(t, ret_stack); -+ } -+} -+ - /* Allocate a return stack for newly created task */ - void ftrace_graph_init_task(struct task_struct *t) - { -@@ -3433,12 +3476,7 @@ void ftrace_graph_init_task(struct task_ - GFP_KERNEL); - if (!ret_stack) - return; -- atomic_set(&t->tracing_graph_pause, 0); -- atomic_set(&t->trace_overrun, 0); -- t->ftrace_timestamp = 0; -- /* make curr_ret_stack visable before we add the ret_stack */ -- smp_wmb(); -- t->ret_stack = ret_stack; -+ graph_init_task(t, ret_stack); - } - } - ---- vanilla-2.6.38.0.orig/arch/x86/kernel/e820.c -+++ vanilla-2.6.38.0/arch/x86/kernel/e820.c -@@ -847,15 +847,21 @@ static int __init parse_memopt(char *p) - if (!p) - return -EINVAL; - --#ifdef CONFIG_X86_32 - if (!strcmp(p, "nopentium")) { -+#ifdef CONFIG_X86_32 - setup_clear_cpu_cap(X86_FEATURE_PSE); - return 0; -- } -+#else -+ printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n"); -+ return -EINVAL; - #endif -+ } - - userdef = 1; - mem_size = memparse(p, &p); -+ /* don't remove all of memory when handling "mem={invalid}" param */ -+ if (mem_size == 0) -+ return -EINVAL; - e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1); - - return 0; ---- vanilla-2.6.38.0.orig/drivers/ata/ahci.c -+++ vanilla-2.6.38.0/drivers/ata/ahci.c -@@ -260,6 +260,7 @@ static const struct pci_device_id ahci_p - { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ - { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ - { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ -+ { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */ - { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ - - /* JMicron 360/1/3/5/6, match class to avoid IDE function */ -@@ -383,6 +384,8 @@ static const struct pci_device_id ahci_p - .class = PCI_CLASS_STORAGE_SATA_AHCI, - .class_mask = 0xffffff, - .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ -+ { PCI_DEVICE(0x1b4b, 0x9125), -+ .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ - - /* Promise */ - { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ ---- vanilla-2.6.38.0.orig/drivers/ata/libata-eh.c -+++ vanilla-2.6.38.0/drivers/ata/libata-eh.c -@@ -1618,7 +1618,7 @@ static void ata_eh_analyze_serror(struct - * host links. For disabled PMP links, only N bit is - * considered as X bit is left at 1 for link plugging. - */ -- if (link->lpm_policy != ATA_LPM_MAX_POWER) -+ if (link->lpm_policy > ATA_LPM_MAX_POWER) - hotplug_mask = 0; /* hotplug doesn't work w/ LPM */ - else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link)) - hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG; ---- vanilla-2.6.38.0.orig/drivers/infiniband/core/cma.c -+++ vanilla-2.6.38.0/drivers/infiniband/core/cma.c -@@ -1210,6 +1210,11 @@ static int cma_req_handler(struct ib_cm_ - cm_id->context = conn_id; - cm_id->cm_handler = cma_ib_handler; - -+ /* -+ * Protect against the user destroying conn_id from another thread -+ * until we're done accessing it. -+ */ -+ atomic_inc(&conn_id->refcount); - ret = conn_id->id.event_handler(&conn_id->id, &event); - if (!ret) { - /* -@@ -1222,8 +1227,10 @@ static int cma_req_handler(struct ib_cm_ - ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); - mutex_unlock(&lock); - mutex_unlock(&conn_id->handler_mutex); -+ cma_deref_id(conn_id); - goto out; - } -+ cma_deref_id(conn_id); - - /* Destroy the CM ID by returning a non-zero value. */ - conn_id->cm_id.ib = NULL; -@@ -1425,17 +1432,25 @@ static int iw_conn_req_handler(struct iw - event.param.conn.private_data_len = iw_event->private_data_len; - event.param.conn.initiator_depth = attr.max_qp_init_rd_atom; - event.param.conn.responder_resources = attr.max_qp_rd_atom; -+ -+ /* -+ * Protect against the user destroying conn_id from another thread -+ * until we're done accessing it. -+ */ -+ atomic_inc(&conn_id->refcount); - ret = conn_id->id.event_handler(&conn_id->id, &event); - if (ret) { - /* User wants to destroy the CM ID */ - conn_id->cm_id.iw = NULL; - cma_exch(conn_id, CMA_DESTROYING); - mutex_unlock(&conn_id->handler_mutex); -+ cma_deref_id(conn_id); - rdma_destroy_id(&conn_id->id); - goto out; - } - - mutex_unlock(&conn_id->handler_mutex); -+ cma_deref_id(conn_id); - - out: - if (dev) ---- vanilla-2.6.38.0.orig/fs/partitions/osf.c -+++ vanilla-2.6.38.0/fs/partitions/osf.c -@@ -10,7 +10,7 @@ - #include "check.h" - #include "osf.h" - --#define MAX_OSF_PARTITIONS 8 -+#define MAX_OSF_PARTITIONS 18 - - int osf_partition(struct parsed_partitions *state) - { ---- vanilla-2.6.38.0.orig/drivers/infiniband/core/cm.c -+++ vanilla-2.6.38.0/drivers/infiniband/core/cm.c -@@ -2989,6 +2989,7 @@ static int cm_sidr_req_handler(struct cm - goto out; /* No match. */ - } - atomic_inc(&cur_cm_id_priv->refcount); -+ atomic_inc(&cm_id_priv->refcount); - spin_unlock_irq(&cm.lock); - - cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler; ---- vanilla-2.6.38.0.orig/arch/x86/kernel/early-quirks.c -+++ vanilla-2.6.38.0/arch/x86/kernel/early-quirks.c -@@ -159,7 +159,12 @@ static void __init ati_bugs_contd(int nu - if (rev >= 0x40) - acpi_fix_pin2_polarity = 1; - -- if (rev > 0x13) -+ /* -+ * SB600: revisions 0x11, 0x12, 0x13, 0x14, ... -+ * SB700: revisions 0x39, 0x3a, ... -+ * SB800: revisions 0x40, 0x41, ... -+ */ -+ if (rev >= 0x39) - return; - - if (acpi_use_timer_override) ---- vanilla-2.6.38.0.orig/arch/microblaze/include/asm/uaccess.h -+++ vanilla-2.6.38.0/arch/microblaze/include/asm/uaccess.h -@@ -120,16 +120,16 @@ static inline unsigned long __must_check - { - /* normal memset with two words to __ex_table */ - __asm__ __volatile__ ( \ -- "1: sb r0, %2, r0;" \ -+ "1: sb r0, %1, r0;" \ - " addik %0, %0, -1;" \ - " bneid %0, 1b;" \ -- " addik %2, %2, 1;" \ -+ " addik %1, %1, 1;" \ - "2: " \ - __EX_TABLE_SECTION \ - ".word 1b,2b;" \ - ".previous;" \ -- : "=r"(n) \ -- : "0"(n), "r"(to) -+ : "=r"(n), "=r"(to) \ -+ : "0"(n), "1"(to) - ); - return n; - } ---- vanilla-2.6.38.0.orig/arch/x86/kernel/alternative.c -+++ vanilla-2.6.38.0/arch/x86/kernel/alternative.c -@@ -620,7 +620,12 @@ static int __kprobes stop_machine_text_p - flush_icache_range((unsigned long)p->addr, - (unsigned long)p->addr + p->len); - } -- -+ /* -+ * Intel Archiecture Software Developer's Manual section 7.1.3 specifies -+ * that a core serializing instruction such as "cpuid" should be -+ * executed on _each_ core before the new instruction is made visible. -+ */ -+ sync_core(); - return 0; - } - ---- vanilla-2.6.38.0.orig/security/tomoyo/file.c -+++ vanilla-2.6.38.0/security/tomoyo/file.c -@@ -927,7 +927,7 @@ int tomoyo_check_open_permission(struct - struct path *path, const int flag) - { - const u8 acc_mode = ACC_MODE(flag); -- int error = -ENOMEM; -+ int error = 0; - struct tomoyo_path_info buf; - struct tomoyo_request_info r; - int idx; -@@ -938,9 +938,6 @@ int tomoyo_check_open_permission(struct - buf.name = NULL; - r.mode = TOMOYO_CONFIG_DISABLED; - idx = tomoyo_read_lock(); -- if (!tomoyo_get_realpath(&buf, path)) -- goto out; -- error = 0; - /* - * If the filename is specified by "deny_rewrite" keyword, - * we need to check "allow_rewrite" permission when the filename is not ---- vanilla-2.6.38.0.orig/drivers/gpu/drm/i915/i915_irq.c -+++ vanilla-2.6.38.0/drivers/gpu/drm/i915/i915_irq.c -@@ -1377,7 +1377,12 @@ int i915_enable_vblank(struct drm_device - else - i915_enable_pipestat(dev_priv, pipe, - PIPE_VBLANK_INTERRUPT_ENABLE); -+ -+ /* maintain vblank delivery even in deep C-states */ -+ if (dev_priv->info->gen == 3) -+ I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16); - spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); -+ - return 0; - } - -@@ -1390,6 +1395,10 @@ void i915_disable_vblank(struct drm_devi - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->irq_lock, irqflags); -+ if (dev_priv->info->gen == 3) -+ I915_WRITE(INSTPM, -+ INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS); -+ - if (HAS_PCH_SPLIT(dev)) - ironlake_disable_display_irq(dev_priv, (pipe == 0) ? - DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); ---- vanilla-2.6.38.0.orig/drivers/gpu/drm/i915/i915_reg.h -+++ vanilla-2.6.38.0/drivers/gpu/drm/i915/i915_reg.h -@@ -405,9 +405,12 @@ - #define I915_ERROR_INSTRUCTION (1<<0) - #define INSTPM 0x020c0 - #define INSTPM_SELF_EN (1<<12) /* 915GM only */ -+#define INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts -+ will not assert AGPBUSY# and will only -+ be delivered when out of C3. */ - #define ACTHD 0x020c8 - #define FW_BLC 0x020d8 --#define FW_BLC2 0x020dc -+#define FW_BLC2 0x020dc - #define FW_BLC_SELF 0x020e0 /* 915+ only */ - #define FW_BLC_SELF_EN_MASK (1<<31) - #define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */ ---- vanilla-2.6.38.0.orig/drivers/gpu/drm/radeon/atombios_crtc.c -+++ vanilla-2.6.38.0/drivers/gpu/drm/radeon/atombios_crtc.c -@@ -61,8 +61,8 @@ static void atombios_overscan_setup(stru - args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); - args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2); - } else if (a2 > a1) { -- args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); -- args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); -+ args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); -+ args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2); - } - break; - case RMX_FULL: ---- vanilla-2.6.38.0.orig/drivers/gpu/drm/drm_sysfs.c -+++ vanilla-2.6.38.0/drivers/gpu/drm/drm_sysfs.c -@@ -158,8 +158,15 @@ static ssize_t status_show(struct device - { - struct drm_connector *connector = to_drm_connector(device); - enum drm_connector_status status; -+ int ret; -+ -+ ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex); -+ if (ret) -+ return ret; - - status = connector->funcs->detect(connector, true); -+ mutex_unlock(&connector->dev->mode_config.mutex); -+ - return snprintf(buf, PAGE_SIZE, "%s\n", - drm_get_connector_status_name(status)); - } ---- vanilla-2.6.38.0.orig/drivers/net/wireless/ath/ath9k/hw.c -+++ vanilla-2.6.38.0/drivers/net/wireless/ath/ath9k/hw.c -@@ -495,6 +495,17 @@ static int __ath9k_hw_init(struct ath_hw - if (ah->hw_version.devid == AR5416_AR9100_DEVID) - ah->hw_version.macVersion = AR_SREV_VERSION_9100; - -+ /* -+ * Read back AR_WA into a permanent copy and set bits 14 and 17. -+ * We need to do this to avoid RMW of this register. We cannot -+ * read the reg when chip is asleep. -+ */ -+ ah->WARegVal = REG_READ(ah, AR_WA); -+ ah->WARegVal |= (AR_WA_D3_L1_DISABLE | -+ AR_WA_ASPM_TIMER_BASED_DISABLE); -+ -+ ath9k_hw_read_revisions(ah); -+ - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - ath_err(common, "Couldn't reset chip\n"); - return -EIO; -@@ -563,14 +574,6 @@ static int __ath9k_hw_init(struct ath_hw - - ath9k_hw_init_mode_regs(ah); - -- /* -- * Read back AR_WA into a permanent copy and set bits 14 and 17. -- * We need to do this to avoid RMW of this register. We cannot -- * read the reg when chip is asleep. -- */ -- ah->WARegVal = REG_READ(ah, AR_WA); -- ah->WARegVal |= (AR_WA_D3_L1_DISABLE | -- AR_WA_ASPM_TIMER_BASED_DISABLE); - - if (ah->is_pciexpress) - ath9k_hw_configpcipowersave(ah, 0, 0); -@@ -1082,8 +1085,6 @@ static bool ath9k_hw_set_reset_power_on( - return false; - } - -- ath9k_hw_read_revisions(ah); -- - return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); - } - ---- vanilla-2.6.38.0.orig/drivers/net/wireless/ath/ath9k/recv.c -+++ vanilla-2.6.38.0/drivers/net/wireless/ath/ath9k/recv.c -@@ -439,9 +439,7 @@ u32 ath_calcrxfilter(struct ath_softc *s - * mode interface or when in monitor mode. AP mode does not need this - * since it receives all in-BSS frames anyway. - */ -- if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && -- (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || -- (sc->sc_ah->is_monitoring)) -+ if (sc->sc_ah->is_monitoring) - rfilt |= ATH9K_RX_FILTER_PROM; - - if (sc->rx.rxfilter & FIF_CONTROL) ---- vanilla-2.6.38.0.orig/drivers/tty/serial/mrst_max3110.c -+++ vanilla-2.6.38.0/drivers/tty/serial/mrst_max3110.c -@@ -51,7 +51,7 @@ - struct uart_max3110 { - struct uart_port port; - struct spi_device *spi; -- char name[24]; -+ char name[SPI_NAME_SIZE]; - - wait_queue_head_t wq; - struct task_struct *main_thread; ---- vanilla-2.6.38.0.orig/drivers/tty/serial/8250.c -+++ vanilla-2.6.38.0/drivers/tty/serial/8250.c -@@ -954,6 +954,23 @@ static int broken_efr(struct uart_8250_p - return 0; - } - -+static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) -+{ -+ unsigned char status; -+ -+ status = serial_in(up, 0x04); /* EXCR2 */ -+#define PRESL(x) ((x) & 0x30) -+ if (PRESL(status) == 0x10) { -+ /* already in high speed mode */ -+ return 0; -+ } else { -+ status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ -+ status |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ -+ serial_outp(up, 0x04, status); -+ } -+ return 1; -+} -+ - /* - * We know that the chip has FIFOs. Does it have an EFR? The - * EFR is located in the same register position as the IIR and -@@ -1025,12 +1042,8 @@ static void autoconfig_16550a(struct uar - quot = serial_dl_read(up); - quot <<= 3; - -- status1 = serial_in(up, 0x04); /* EXCR2 */ -- status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ -- status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ -- serial_outp(up, 0x04, status1); -- -- serial_dl_write(up, quot); -+ if (ns16550a_goto_highspeed(up)) -+ serial_dl_write(up, quot); - - serial_outp(up, UART_LCR, 0); - -@@ -3025,17 +3038,13 @@ void serial8250_resume_port(int line) - struct uart_8250_port *up = &serial8250_ports[line]; - - if (up->capabilities & UART_NATSEMI) { -- unsigned char tmp; -- - /* Ensure it's still in high speed mode */ - serial_outp(up, UART_LCR, 0xE0); - -- tmp = serial_in(up, 0x04); /* EXCR2 */ -- tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ -- tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ -- serial_outp(up, 0x04, tmp); -+ ns16550a_goto_highspeed(up); - - serial_outp(up, UART_LCR, 0); -+ up->port.uartclk = 921600*16; - } - uart_resume_port(&serial8250_reg, &up->port); - } ---- vanilla-2.6.38.0.orig/drivers/usb/serial/usb-serial.c -+++ vanilla-2.6.38.0/drivers/usb/serial/usb-serial.c -@@ -911,9 +911,8 @@ int usb_serial_probe(struct usb_interfac - dev_err(&interface->dev, "No free urbs available\n"); - goto probe_error; - } -- buffer_size = serial->type->bulk_in_size; -- if (!buffer_size) -- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); -+ buffer_size = max_t(int, serial->type->bulk_in_size, -+ le16_to_cpu(endpoint->wMaxPacketSize)); - port->bulk_in_size = buffer_size; - port->bulk_in_endpointAddress = endpoint->bEndpointAddress; - port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); ---- vanilla-2.6.38.0.orig/include/linux/usb/serial.h -+++ vanilla-2.6.38.0/include/linux/usb/serial.h -@@ -191,7 +191,8 @@ static inline void usb_set_serial_data(s - * @id_table: pointer to a list of usb_device_id structures that define all - * of the devices this structure can support. - * @num_ports: the number of different ports this device will have. -- * @bulk_in_size: bytes to allocate for bulk-in buffer (0 = end-point size) -+ * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer -+ * (0 = end-point size) - * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size) - * @calc_num_ports: pointer to a function to determine how many ports this - * device has dynamically. It will be called after the probe() ---- vanilla-2.6.38.0.orig/drivers/usb/serial/kobil_sct.c -+++ vanilla-2.6.38.0/drivers/usb/serial/kobil_sct.c -@@ -372,7 +372,7 @@ static void kobil_read_int_callback(stru - } - - tty = tty_port_tty_get(&port->port); -- if (urb->actual_length) { -+ if (tty && urb->actual_length) { - - /* BEGIN DEBUG */ - /* ---- vanilla-2.6.38.0.orig/drivers/usb/serial/option.c -+++ vanilla-2.6.38.0/drivers/usb/serial/option.c -@@ -652,7 +652,8 @@ static const struct usb_device_id option - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, -- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, -+ 0xff, 0xff), .driver_info = (kernel_ulong_t)&four_g_w14_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) }, ---- vanilla-2.6.38.0.orig/drivers/usb/serial/ch341.c -+++ vanilla-2.6.38.0/drivers/usb/serial/ch341.c -@@ -75,6 +75,7 @@ static int debug; - static const struct usb_device_id id_table[] = { - { USB_DEVICE(0x4348, 0x5523) }, - { USB_DEVICE(0x1a86, 0x7523) }, -+ { USB_DEVICE(0x1a86, 0x5523) }, - { }, - }; - MODULE_DEVICE_TABLE(usb, id_table); ---- vanilla-2.6.38.0.orig/drivers/staging/winbond/core.h -+++ vanilla-2.6.38.0/drivers/staging/winbond/core.h -@@ -3,6 +3,7 @@ - - #include - #include -+#include - - #include "wbhal.h" - #include "mto.h" ---- vanilla-2.6.38.0.orig/drivers/staging/tidspbridge/rmgr/proc.c -+++ vanilla-2.6.38.0/drivers/staging/tidspbridge/rmgr/proc.c -@@ -781,12 +781,14 @@ int proc_begin_dma(void *hprocessor, voi - (u32)pmpu_addr, - ul_size, dir); - -+ mutex_lock(&proc_lock); -+ - /* find requested memory are in cached mapping information */ - map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size); - if (!map_obj) { - pr_err("%s: find_containing_mapping failed\n", __func__); - status = -EFAULT; -- goto err_out; -+ goto no_map; - } - - if (memory_give_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) { -@@ -795,6 +797,8 @@ int proc_begin_dma(void *hprocessor, voi - status = -EFAULT; - } - -+no_map: -+ mutex_unlock(&proc_lock); - err_out: - - return status; -@@ -819,21 +823,24 @@ int proc_end_dma(void *hprocessor, void - (u32)pmpu_addr, - ul_size, dir); - -+ mutex_lock(&proc_lock); -+ - /* find requested memory are in cached mapping information */ - map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size); - if (!map_obj) { - pr_err("%s: find_containing_mapping failed\n", __func__); - status = -EFAULT; -- goto err_out; -+ goto no_map; - } - - if (memory_regain_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) { - pr_err("%s: InValid address parameters %p %x\n", - __func__, pmpu_addr, ul_size); - status = -EFAULT; -- goto err_out; - } - -+no_map: -+ mutex_unlock(&proc_lock); - err_out: - return status; - } -@@ -1726,9 +1733,8 @@ int proc_un_map(void *hprocessor, void * - (p_proc_object->hbridge_context, va_align, size_align); - } - -- mutex_unlock(&proc_lock); - if (status) -- goto func_end; -+ goto unmap_failed; - - /* - * A successful unmap should be followed by removal of map_obj -@@ -1737,6 +1743,9 @@ int proc_un_map(void *hprocessor, void * - */ - remove_mapping_information(pr_ctxt, (u32) map_addr, size_align); - -+unmap_failed: -+ mutex_unlock(&proc_lock); -+ - func_end: - dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n", - __func__, hprocessor, map_addr, status); ---- vanilla-2.6.38.0.orig/drivers/net/wireless/rtl818x/rtl8187/dev.c -+++ vanilla-2.6.38.0/drivers/net/wireless/rtl818x/rtl8187/dev.c -@@ -871,23 +871,35 @@ static void rtl8187_work(struct work_str - /* The RTL8187 returns the retry count through register 0xFFFA. In - * addition, it appears to be a cumulative retry count, not the - * value for the current TX packet. When multiple TX entries are -- * queued, the retry count will be valid for the last one in the queue. -- * The "error" should not matter for purposes of rate setting. */ -+ * waiting in the queue, the retry count will be the total for all. -+ * The "error" may matter for purposes of rate setting, but there is -+ * no other choice with this hardware. -+ */ - struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, - work.work); - struct ieee80211_tx_info *info; - struct ieee80211_hw *dev = priv->dev; - static u16 retry; - u16 tmp; -+ u16 avg_retry; -+ int length; - - mutex_lock(&priv->conf_mutex); - tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA); -+ length = skb_queue_len(&priv->b_tx_status.queue); -+ if (unlikely(!length)) -+ length = 1; -+ if (unlikely(tmp < retry)) -+ tmp = retry; -+ avg_retry = (tmp - retry) / length; - while (skb_queue_len(&priv->b_tx_status.queue) > 0) { - struct sk_buff *old_skb; - - old_skb = skb_dequeue(&priv->b_tx_status.queue); - info = IEEE80211_SKB_CB(old_skb); -- info->status.rates[0].count = tmp - retry + 1; -+ info->status.rates[0].count = avg_retry + 1; -+ if (info->status.rates[0].count > RETRY_COUNT) -+ info->flags &= ~IEEE80211_TX_STAT_ACK; - ieee80211_tx_status_irqsafe(dev, old_skb); - } - retry = tmp; -@@ -933,8 +945,8 @@ static int rtl8187_start(struct ieee8021 - rtl818x_iowrite32(priv, &priv->map->TX_CONF, - RTL818X_TX_CONF_HW_SEQNUM | - RTL818X_TX_CONF_DISREQQSIZE | -- (7 << 8 /* short retry limit */) | -- (7 << 0 /* long retry limit */) | -+ (RETRY_COUNT << 8 /* short retry limit */) | -+ (RETRY_COUNT << 0 /* long retry limit */) | - (7 << 21 /* MAX TX DMA */)); - rtl8187_init_urbs(dev); - rtl8187b_init_status_urb(dev); -@@ -1378,6 +1390,9 @@ static int __devinit rtl8187_probe(struc - dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_RX_INCLUDES_FCS; -+ /* Initialize rate-control variables */ -+ dev->max_rates = 1; -+ dev->max_rate_tries = RETRY_COUNT; - - eeprom.data = dev; - eeprom.register_read = rtl8187_eeprom_register_read; ---- vanilla-2.6.38.0.orig/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h -+++ vanilla-2.6.38.0/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h -@@ -35,6 +35,8 @@ - #define RFKILL_MASK_8187_89_97 0x2 - #define RFKILL_MASK_8198 0x4 - -+#define RETRY_COUNT 7 -+ - struct rtl8187_rx_info { - struct urb *urb; - struct ieee80211_hw *dev; ---- vanilla-2.6.38.0.orig/drivers/usb/host/isp1760-hcd.c -+++ vanilla-2.6.38.0/drivers/usb/host/isp1760-hcd.c -@@ -33,6 +33,7 @@ struct isp1760_hcd { - struct inter_packet_info atl_ints[32]; - struct inter_packet_info int_ints[32]; - struct memory_chunk memory_pool[BLOCKS]; -+ u32 atl_queued; - - /* periodic schedule support */ - #define DEFAULT_I_TDPS 1024 -@@ -850,6 +851,11 @@ static void enqueue_an_ATL_packet(struct - skip_map &= ~queue_entry; - isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG); - -+ priv->atl_queued++; -+ if (priv->atl_queued == 2) -+ isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, -+ hcd->regs + HC_INTERRUPT_ENABLE); -+ - buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG); - buffstatus |= ATL_BUFFER; - isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG); -@@ -992,6 +998,7 @@ static void do_atl_int(struct usb_hcd *u - u32 dw3; - - status = 0; -+ priv->atl_queued--; - - queue_entry = __ffs(done_map); - done_map &= ~(1 << queue_entry); -@@ -1054,11 +1061,6 @@ static void do_atl_int(struct usb_hcd *u - * device is not able to send data fast enough. - * This happens mostly on slower hardware. - */ -- printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: " -- "%d of %zu done: %08x cur: %08x\n", qtd, -- urb, qh, PTD_XFERRED_LENGTH(dw3), -- qtd->length, done_map, -- (1 << queue_entry)); - - /* RL counter = ERR counter */ - dw3 &= ~(0xf << 19); -@@ -1086,6 +1088,11 @@ static void do_atl_int(struct usb_hcd *u - priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + - atl_regs, sizeof(ptd)); - -+ priv->atl_queued++; -+ if (priv->atl_queued == 2) -+ isp1760_writel(INTERRUPT_ENABLE_SOT_MASK, -+ usb_hcd->regs + HC_INTERRUPT_ENABLE); -+ - buffstatus = isp1760_readl(usb_hcd->regs + - HC_BUFFER_STATUS_REG); - buffstatus |= ATL_BUFFER; -@@ -1191,6 +1198,9 @@ static void do_atl_int(struct usb_hcd *u - skip_map = isp1760_readl(usb_hcd->regs + - HC_ATL_PTD_SKIPMAP_REG); - } -+ if (priv->atl_queued <= 1) -+ isp1760_writel(INTERRUPT_ENABLE_MASK, -+ usb_hcd->regs + HC_INTERRUPT_ENABLE); - } - - static void do_intl_int(struct usb_hcd *usb_hcd) -@@ -1770,7 +1780,7 @@ static irqreturn_t isp1760_irq(struct us - goto leave; - - isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG); -- if (imask & HC_ATL_INT) -+ if (imask & (HC_ATL_INT | HC_SOT_INT)) - do_atl_int(usb_hcd); - - if (imask & HC_INTL_INT) ---- vanilla-2.6.38.0.orig/drivers/usb/host/isp1760-hcd.h -+++ vanilla-2.6.38.0/drivers/usb/host/isp1760-hcd.h -@@ -69,6 +69,7 @@ void deinit_kmem_cache(void); - - #define HC_INTERRUPT_ENABLE 0x314 - #define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT) -+#define INTERRUPT_ENABLE_SOT_MASK (HC_INTL_INT | HC_SOT_INT | HC_EOT_INT) - - #define HC_ISO_INT (1 << 9) - #define HC_ATL_INT (1 << 8) ---- vanilla-2.6.38.0.orig/drivers/usb/host/ehci-hub.c -+++ vanilla-2.6.38.0/drivers/usb/host/ehci-hub.c -@@ -106,6 +106,27 @@ static void ehci_handover_companion_port - ehci->owned_ports = 0; - } - -+static int ehci_port_change(struct ehci_hcd *ehci) -+{ -+ int i = HCS_N_PORTS(ehci->hcs_params); -+ -+ /* First check if the controller indicates a change event */ -+ -+ if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD) -+ return 1; -+ -+ /* -+ * Not all controllers appear to update this while going from D3 to D0, -+ * so check the individual port status registers as well -+ */ -+ -+ while (i--) -+ if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC) -+ return 1; -+ -+ return 0; -+} -+ - static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, - bool suspending, bool do_wakeup) - { -@@ -173,7 +194,7 @@ static void ehci_adjust_port_wakeup_flag - } - - /* Does the root hub have a port wakeup pending? */ -- if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)) -+ if (!suspending && ehci_port_change(ehci)) - usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); - - spin_unlock_irqrestore(&ehci->lock, flags); ---- vanilla-2.6.38.0.orig/drivers/usb/core/hcd-pci.c -+++ vanilla-2.6.38.0/drivers/usb/core/hcd-pci.c -@@ -363,8 +363,7 @@ static int check_root_hub_suspended(stru - struct pci_dev *pci_dev = to_pci_dev(dev); - struct usb_hcd *hcd = pci_get_drvdata(pci_dev); - -- if (!(hcd->state == HC_STATE_SUSPENDED || -- hcd->state == HC_STATE_HALT)) { -+ if (HCD_RH_RUNNING(hcd)) { - dev_warn(dev, "Root hub is not suspended\n"); - return -EBUSY; - } -@@ -386,7 +385,7 @@ static int suspend_common(struct device - if (retval) - return retval; - -- if (hcd->driver->pci_suspend) { -+ if (hcd->driver->pci_suspend && !HCD_DEAD(hcd)) { - /* Optimization: Don't suspend if a root-hub wakeup is - * pending and it would cause the HCD to wake up anyway. - */ -@@ -427,7 +426,7 @@ static int resume_common(struct device * - struct usb_hcd *hcd = pci_get_drvdata(pci_dev); - int retval; - -- if (hcd->state != HC_STATE_SUSPENDED) { -+ if (HCD_RH_RUNNING(hcd)) { - dev_dbg(dev, "can't resume, not suspended!\n"); - return 0; - } -@@ -442,7 +441,7 @@ static int resume_common(struct device * - - clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); - -- if (hcd->driver->pci_resume) { -+ if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) { - if (event != PM_EVENT_AUTO_RESUME) - wait_for_companions(pci_dev, hcd); - -@@ -475,10 +474,10 @@ static int hcd_pci_suspend_noirq(struct - - pci_save_state(pci_dev); - -- /* If the root hub is HALTed rather than SUSPENDed, -+ /* If the root hub is dead rather than suspended, - * disallow remote wakeup. - */ -- if (hcd->state == HC_STATE_HALT) -+ if (HCD_DEAD(hcd)) - device_set_wakeup_enable(dev, 0); - dev_dbg(dev, "wakeup: %d\n", device_may_wakeup(dev)); - ---- vanilla-2.6.38.0.orig/drivers/usb/core/hcd.c -+++ vanilla-2.6.38.0/drivers/usb/core/hcd.c -@@ -983,7 +983,7 @@ static int register_root_hub(struct usb_ - spin_unlock_irq (&hcd_root_hub_lock); - - /* Did the HC die before the root hub was registered? */ -- if (hcd->state == HC_STATE_HALT) -+ if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT) - usb_hc_died (hcd); /* This time clean up */ - } - -@@ -1089,13 +1089,10 @@ int usb_hcd_link_urb_to_ep(struct usb_hc - * Check the host controller's state and add the URB to the - * endpoint's queue. - */ -- switch (hcd->state) { -- case HC_STATE_RUNNING: -- case HC_STATE_RESUMING: -+ if (HCD_RH_RUNNING(hcd)) { - urb->unlinked = 0; - list_add_tail(&urb->urb_list, &urb->ep->urb_list); -- break; -- default: -+ } else { - rc = -ESHUTDOWN; - goto done; - } -@@ -1913,7 +1910,7 @@ int usb_hcd_get_frame_number (struct usb - { - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - -- if (!HC_IS_RUNNING (hcd->state)) -+ if (!HCD_RH_RUNNING(hcd)) - return -ESHUTDOWN; - return hcd->driver->get_frame_number (hcd); - } -@@ -1930,9 +1927,15 @@ int hcd_bus_suspend(struct usb_device *r - - dev_dbg(&rhdev->dev, "bus %s%s\n", - (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend"); -+ if (HCD_DEAD(hcd)) { -+ dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend"); -+ return 0; -+ } -+ - if (!hcd->driver->bus_suspend) { - status = -ENOENT; - } else { -+ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); - hcd->state = HC_STATE_QUIESCING; - status = hcd->driver->bus_suspend(hcd); - } -@@ -1940,7 +1943,12 @@ int hcd_bus_suspend(struct usb_device *r - usb_set_device_state(rhdev, USB_STATE_SUSPENDED); - hcd->state = HC_STATE_SUSPENDED; - } else { -- hcd->state = old_state; -+ spin_lock_irq(&hcd_root_hub_lock); -+ if (!HCD_DEAD(hcd)) { -+ set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); -+ hcd->state = old_state; -+ } -+ spin_unlock_irq(&hcd_root_hub_lock); - dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", - "suspend", status); - } -@@ -1955,9 +1963,13 @@ int hcd_bus_resume(struct usb_device *rh - - dev_dbg(&rhdev->dev, "usb %s%s\n", - (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); -+ if (HCD_DEAD(hcd)) { -+ dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume"); -+ return 0; -+ } - if (!hcd->driver->bus_resume) - return -ENOENT; -- if (hcd->state == HC_STATE_RUNNING) -+ if (HCD_RH_RUNNING(hcd)) - return 0; - - hcd->state = HC_STATE_RESUMING; -@@ -1966,10 +1978,15 @@ int hcd_bus_resume(struct usb_device *rh - if (status == 0) { - /* TRSMRCY = 10 msec */ - msleep(10); -- usb_set_device_state(rhdev, rhdev->actconfig -- ? USB_STATE_CONFIGURED -- : USB_STATE_ADDRESS); -- hcd->state = HC_STATE_RUNNING; -+ spin_lock_irq(&hcd_root_hub_lock); -+ if (!HCD_DEAD(hcd)) { -+ usb_set_device_state(rhdev, rhdev->actconfig -+ ? USB_STATE_CONFIGURED -+ : USB_STATE_ADDRESS); -+ set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); -+ hcd->state = HC_STATE_RUNNING; -+ } -+ spin_unlock_irq(&hcd_root_hub_lock); - } else { - hcd->state = old_state; - dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", -@@ -2080,7 +2097,7 @@ irqreturn_t usb_hcd_irq (int irq, void * - */ - local_irq_save(flags); - -- if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) { -+ if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) { - rc = IRQ_NONE; - } else if (hcd->driver->irq(hcd) == IRQ_NONE) { - rc = IRQ_NONE; -@@ -2114,6 +2131,8 @@ void usb_hc_died (struct usb_hcd *hcd) - dev_err (hcd->self.controller, "HC died; cleaning up\n"); - - spin_lock_irqsave (&hcd_root_hub_lock, flags); -+ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); -+ set_bit(HCD_FLAG_DEAD, &hcd->flags); - if (hcd->rh_registered) { - clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - -@@ -2256,6 +2275,12 @@ int usb_add_hcd(struct usb_hcd *hcd, - */ - device_init_wakeup(&rhdev->dev, 1); - -+ /* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is -+ * registered. But since the controller can die at any time, -+ * let's initialize the flag before touching the hardware. -+ */ -+ set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); -+ - /* "reset" is misnamed; its role is now one-time init. the controller - * should already have been reset (and boot firmware kicked off etc). - */ -@@ -2323,6 +2348,7 @@ int usb_add_hcd(struct usb_hcd *hcd, - return retval; - - error_create_attr_group: -+ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); - if (HC_IS_RUNNING(hcd->state)) - hcd->state = HC_STATE_QUIESCING; - spin_lock_irq(&hcd_root_hub_lock); -@@ -2375,6 +2401,7 @@ void usb_remove_hcd(struct usb_hcd *hcd) - usb_get_dev(rhdev); - sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group); - -+ clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags); - if (HC_IS_RUNNING (hcd->state)) - hcd->state = HC_STATE_QUIESCING; - ---- vanilla-2.6.38.0.orig/include/linux/usb/hcd.h -+++ vanilla-2.6.38.0/include/linux/usb/hcd.h -@@ -99,6 +99,8 @@ struct usb_hcd { - #define HCD_FLAG_POLL_RH 2 /* poll for rh status? */ - #define HCD_FLAG_POLL_PENDING 3 /* status has changed? */ - #define HCD_FLAG_WAKEUP_PENDING 4 /* root hub is resuming? */ -+#define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */ -+#define HCD_FLAG_DEAD 6 /* controller has died? */ - - /* The flags can be tested using these macros; they are likely to - * be slightly faster than test_bit(). -@@ -108,6 +110,8 @@ struct usb_hcd { - #define HCD_POLL_RH(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_RH)) - #define HCD_POLL_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING)) - #define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING)) -+#define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING)) -+#define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD)) - - /* Flags that get set only during HCD registration or removal. */ - unsigned rh_registered:1;/* is root hub registered? */ ---- vanilla-2.6.38.0.orig/drivers/usb/host/xhci-ring.c -+++ vanilla-2.6.38.0/drivers/usb/host/xhci-ring.c -@@ -500,15 +500,26 @@ void xhci_find_new_dequeue_state(struct - state->new_cycle_state = ~(state->new_cycle_state) & 0x1; - next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr); - -+ /* -+ * If there is only one segment in a ring, find_trb_seg()'s while loop -+ * will not run, and it will return before it has a chance to see if it -+ * needs to toggle the cycle bit. It can't tell if the stalled transfer -+ * ended just before the link TRB on a one-segment ring, or if the TD -+ * wrapped around the top of the ring, because it doesn't have the TD in -+ * question. Look for the one-segment case where stalled TRB's address -+ * is greater than the new dequeue pointer address. -+ */ -+ if (ep_ring->first_seg == ep_ring->first_seg->next && -+ state->new_deq_ptr < dev->eps[ep_index].stopped_trb) -+ state->new_cycle_state ^= 0x1; -+ xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state); -+ - /* Don't update the ring cycle state for the producer (us). */ - xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n", - state->new_deq_seg); - addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr); - xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n", - (unsigned long long) addr); -- xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n"); -- ep_ring->dequeue = state->new_deq_ptr; -- ep_ring->deq_seg = state->new_deq_seg; - } - - static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, -@@ -951,9 +962,26 @@ static void handle_set_deq_completion(st - } else { - xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n", - ep_ctx->deq); -+ if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg, -+ dev->eps[ep_index].queued_deq_ptr) == -+ (ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) { -+ /* Update the ring's dequeue segment and dequeue pointer -+ * to reflect the new position. -+ */ -+ ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg; -+ ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr; -+ } else { -+ xhci_warn(xhci, "Mismatch between completed Set TR Deq " -+ "Ptr command & xHCI internal state.\n"); -+ xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n", -+ dev->eps[ep_index].queued_deq_seg, -+ dev->eps[ep_index].queued_deq_ptr); -+ } - } - - dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING; -+ dev->eps[ep_index].queued_deq_seg = NULL; -+ dev->eps[ep_index].queued_deq_ptr = NULL; - /* Restart any rings with pending URBs */ - ring_doorbell_for_active_rings(xhci, slot_id, ep_index); - } -@@ -3229,6 +3257,7 @@ static int queue_set_tr_deq(struct xhci_ - u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); - u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id); - u32 type = TRB_TYPE(TRB_SET_DEQ); -+ struct xhci_virt_ep *ep; - - addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr); - if (addr == 0) { -@@ -3237,6 +3266,14 @@ static int queue_set_tr_deq(struct xhci_ - deq_seg, deq_ptr); - return 0; - } -+ ep = &xhci->devs[slot_id]->eps[ep_index]; -+ if ((ep->ep_state & SET_DEQ_PENDING)) { -+ xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n"); -+ xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n"); -+ return 0; -+ } -+ ep->queued_deq_seg = deq_seg; -+ ep->queued_deq_ptr = deq_ptr; - return queue_command(xhci, lower_32_bits(addr) | cycle_state, - upper_32_bits(addr), trb_stream_id, - trb_slot_id | trb_ep_index | type, false); ---- vanilla-2.6.38.0.orig/drivers/usb/host/xhci.h -+++ vanilla-2.6.38.0/drivers/usb/host/xhci.h -@@ -644,6 +644,9 @@ struct xhci_ep_ctx { - #define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) - #define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) - -+/* deq bitmasks */ -+#define EP_CTX_CYCLE_MASK (1 << 0) -+ - - /** - * struct xhci_input_control_context -@@ -746,6 +749,12 @@ struct xhci_virt_ep { - struct timer_list stop_cmd_timer; - int stop_cmds_pending; - struct xhci_hcd *xhci; -+ /* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue -+ * command. We'll need to update the ring's dequeue segment and dequeue -+ * pointer after the command completes. -+ */ -+ struct xhci_segment *queued_deq_seg; -+ union xhci_trb *queued_deq_ptr; - /* - * Sometimes the xHC can not process isochronous endpoint ring quickly - * enough, and it will miss some isoc tds on the ring and generate ---- vanilla-2.6.38.0.orig/drivers/usb/core/urb.c -+++ vanilla-2.6.38.0/drivers/usb/core/urb.c -@@ -366,7 +366,16 @@ int usb_submit_urb(struct urb *urb, gfp_ - if (xfertype == USB_ENDPOINT_XFER_ISOC) { - int n, len; - -- /* FIXME SuperSpeed isoc endpoints have up to 16 bursts */ -+ /* SuperSpeed isoc endpoints have up to 16 bursts of up to -+ * 3 packets each -+ */ -+ if (dev->speed == USB_SPEED_SUPER) { -+ int burst = 1 + ep->ss_ep_comp.bMaxBurst; -+ int mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes); -+ max *= burst; -+ max *= mult; -+ } -+ - /* "high bandwidth" mode, 1-3 packets/uframe? */ - if (dev->speed == USB_SPEED_HIGH) { - int mult = 1 + ((max >> 11) & 0x03); ---- vanilla-2.6.38.0.orig/include/linux/usb/ch9.h -+++ vanilla-2.6.38.0/include/linux/usb/ch9.h -@@ -585,6 +585,8 @@ struct usb_ss_ep_comp_descriptor { - #define USB_DT_SS_EP_COMP_SIZE 6 - /* Bits 4:0 of bmAttributes if this is a bulk endpoint */ - #define USB_SS_MAX_STREAMS(p) (1 << (p & 0x1f)) -+/* Bits 1:0 of bmAttributes if this is an isoc endpoint */ -+#define USB_SS_MULT(p) (1 + ((p) & 0x3)) - - /*-------------------------------------------------------------------------*/ - ---- vanilla-2.6.38.0.orig/sound/pci/hda/patch_realtek.c -+++ vanilla-2.6.38.0/sound/pci/hda/patch_realtek.c -@@ -394,6 +394,7 @@ struct alc_spec { - /* other flags */ - unsigned int no_analog :1; /* digital I/O only */ - unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ -+ unsigned int single_input_src:1; - int init_amp; - int codec_variant; /* flag for other variants */ - -@@ -3919,6 +3920,8 @@ static struct hda_amp_list alc880_lg_loo - * Common callbacks - */ - -+static void alc_init_special_input_src(struct hda_codec *codec); -+ - static int alc_init(struct hda_codec *codec) - { - struct alc_spec *spec = codec->spec; -@@ -3929,6 +3932,7 @@ static int alc_init(struct hda_codec *co - - for (i = 0; i < spec->num_init_verbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); -+ alc_init_special_input_src(codec); - - if (spec->init_hook) - spec->init_hook(codec); -@@ -5151,7 +5155,9 @@ static const char *alc_get_line_out_pfx( - - switch (cfg->line_out_type) { - case AUTO_PIN_SPEAKER_OUT: -- return "Speaker"; -+ if (cfg->line_outs == 1) -+ return "Speaker"; -+ break; - case AUTO_PIN_HP_OUT: - return "Headphone"; - default: -@@ -5205,16 +5211,19 @@ static int alc880_auto_create_multi_out_ - return err; - } else { - const char *name = pfx; -- if (!name) -+ int index = i; -+ if (!name) { - name = chname[i]; -+ index = 0; -+ } - err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, -- name, i, -+ name, index, - HDA_COMPOSE_AMP_VAL(nid, 3, 0, - HDA_OUTPUT)); - if (err < 0) - return err; - err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, -- name, i, -+ name, index, - HDA_COMPOSE_AMP_VAL(nid, 3, 2, - HDA_INPUT)); - if (err < 0) -@@ -5585,6 +5594,7 @@ static void fixup_single_adc(struct hda_ - spec->capsrc_nids += i; - spec->adc_nids += i; - spec->num_adc_nids = 1; -+ spec->single_input_src = 1; - } - } - -@@ -5596,6 +5606,16 @@ static void fixup_dual_adc_switch(struct - init_capsrc_for_pin(codec, spec->int_mic.pin); - } - -+/* initialize some special cases for input sources */ -+static void alc_init_special_input_src(struct hda_codec *codec) -+{ -+ struct alc_spec *spec = codec->spec; -+ if (spec->dual_adc_switch) -+ fixup_dual_adc_switch(codec); -+ else if (spec->single_input_src) -+ init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin); -+} -+ - static void set_capture_mixer(struct hda_codec *codec) - { - struct alc_spec *spec = codec->spec; -@@ -5611,7 +5631,7 @@ static void set_capture_mixer(struct hda - int mux = 0; - int num_adcs = spec->num_adc_nids; - if (spec->dual_adc_switch) -- fixup_dual_adc_switch(codec); -+ num_adcs = 1; - else if (spec->auto_mic) - fixup_automic_adc(codec); - else if (spec->input_mux) { -@@ -5620,8 +5640,6 @@ static void set_capture_mixer(struct hda - else if (spec->input_mux->num_items == 1) - fixup_single_adc(codec); - } -- if (spec->dual_adc_switch) -- num_adcs = 1; - spec->cap_mixer = caps[mux][num_adcs - 1]; - } - } -@@ -10748,6 +10766,7 @@ static struct alc_config_preset alc882_p - */ - enum { - PINFIX_ABIT_AW9D_MAX, -+ PINFIX_LENOVO_Y530, - PINFIX_PB_M5210, - PINFIX_ACER_ASPIRE_7736, - }; -@@ -10762,6 +10781,14 @@ static const struct alc_fixup alc882_fix - { } - } - }, -+ [PINFIX_LENOVO_Y530] = { -+ .type = ALC_FIXUP_PINS, -+ .v.pins = (const struct alc_pincfg[]) { -+ { 0x15, 0x99130112 }, /* rear int speakers */ -+ { 0x16, 0x99130111 }, /* subwoofer */ -+ { } -+ } -+ }, - [PINFIX_PB_M5210] = { - .type = ALC_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { -@@ -10777,6 +10804,7 @@ static const struct alc_fixup alc882_fix - - static struct snd_pci_quirk alc882_fixup_tbl[] = { - SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), -+ SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530), - SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), - SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736), - {} -@@ -10829,23 +10857,28 @@ static void alc882_auto_init_hp_out(stru - hda_nid_t pin, dac; - int i; - -- for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { -- pin = spec->autocfg.hp_pins[i]; -- if (!pin) -- break; -- dac = spec->multiout.hp_nid; -- if (!dac) -- dac = spec->multiout.dac_nids[0]; /* to front */ -- alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); -+ if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) { -+ for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { -+ pin = spec->autocfg.hp_pins[i]; -+ if (!pin) -+ break; -+ dac = spec->multiout.hp_nid; -+ if (!dac) -+ dac = spec->multiout.dac_nids[0]; /* to front */ -+ alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); -+ } - } -- for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { -- pin = spec->autocfg.speaker_pins[i]; -- if (!pin) -- break; -- dac = spec->multiout.extra_out_nid[0]; -- if (!dac) -- dac = spec->multiout.dac_nids[0]; /* to front */ -- alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); -+ -+ if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) { -+ for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { -+ pin = spec->autocfg.speaker_pins[i]; -+ if (!pin) -+ break; -+ dac = spec->multiout.extra_out_nid[0]; -+ if (!dac) -+ dac = spec->multiout.dac_nids[0]; /* to front */ -+ alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); -+ } - } - } - ---- vanilla-2.6.38.0.orig/sound/pci/hda/patch_sigmatel.c -+++ vanilla-2.6.38.0/sound/pci/hda/patch_sigmatel.c -@@ -757,7 +757,7 @@ static int stac92xx_mux_enum_put(struct - struct sigmatel_spec *spec = codec->spec; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - const struct hda_input_mux *imux = spec->input_mux; -- unsigned int idx, prev_idx; -+ unsigned int idx, prev_idx, didx; - - idx = ucontrol->value.enumerated.item[0]; - if (idx >= imux->num_items) -@@ -769,7 +769,8 @@ static int stac92xx_mux_enum_put(struct - snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, - AC_VERB_SET_CONNECT_SEL, - imux->items[idx].index); -- if (prev_idx >= spec->num_analog_muxes) { -+ if (prev_idx >= spec->num_analog_muxes && -+ spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) { - imux = spec->dinput_mux; - /* 0 = analog */ - snd_hda_codec_write_cache(codec, -@@ -779,9 +780,13 @@ static int stac92xx_mux_enum_put(struct - } - } else { - imux = spec->dinput_mux; -+ /* first dimux item is hardcoded to select analog imux, -+ * so lets skip it -+ */ -+ didx = idx - spec->num_analog_muxes + 1; - snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, - AC_VERB_SET_CONNECT_SEL, -- imux->items[idx - 1].index); -+ imux->items[didx].index); - } - spec->cur_mux[adc_idx] = idx; - return 1; ---- vanilla-2.6.38.0.orig/drivers/hid/hid-magicmouse.c -+++ vanilla-2.6.38.0/drivers/hid/hid-magicmouse.c -@@ -258,7 +258,7 @@ static void magicmouse_emit_touch(struct - input_report_abs(input, ABS_MT_TRACKING_ID, id); - input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); - input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); -- input_report_abs(input, ABS_MT_ORIENTATION, orientation); -+ input_report_abs(input, ABS_MT_ORIENTATION, -orientation); - input_report_abs(input, ABS_MT_POSITION_X, x); - input_report_abs(input, ABS_MT_POSITION_Y, y); - -@@ -397,7 +397,7 @@ static void magicmouse_setup_input(struc - input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); - input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); -- input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0); -+ input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0); - - /* Note: Touch Y position from the device is inverted relative - * to how pointer motion is reported (and relative to how USB ---- vanilla-2.6.38.0.orig/drivers/hid/Kconfig -+++ vanilla-2.6.38.0/drivers/hid/Kconfig -@@ -68,9 +68,15 @@ config HID_A4TECH - ---help--- - Support for A4 tech X5 and WOP-35 / Trust 450L mice. - --config HID_ACRUX_FF -- tristate "ACRUX force feedback" -+config HID_ACRUX -+ tristate "ACRUX game controller support" - depends on USB_HID -+ ---help--- -+ Say Y here if you want to enable support for ACRUX game controllers. -+ -+config HID_ACRUX_FF -+ tristate "ACRUX force feedback support" -+ depends on HID_ACRUX - select INPUT_FF_MEMLESS - ---help--- - Say Y here if you want to enable force feedback support for ACRUX -@@ -319,10 +325,10 @@ config HID_NTRIG - Support for N-Trig touch screen. - - config HID_ORTEK -- tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad" -+ tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad" - depends on USB_HID - ---help--- -- Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. -+ Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad. - - config HID_PANTHERLORD - tristate "Pantherlord/GreenAsia game controller" ---- vanilla-2.6.38.0.orig/drivers/hid/hid-core.c -+++ vanilla-2.6.38.0/drivers/hid/hid-core.c -@@ -1256,9 +1256,7 @@ static const struct hid_device_id hid_ha - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, --#if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE) - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, --#endif - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, -@@ -1302,6 +1300,9 @@ static const struct hid_device_id hid_ha - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, -@@ -1400,6 +1401,7 @@ static const struct hid_device_id hid_ha - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, -@@ -1801,6 +1803,9 @@ static const struct hid_device_id hid_mo - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { } ---- vanilla-2.6.38.0.orig/drivers/hid/hid-ids.h -+++ vanilla-2.6.38.0/drivers/hid/hid-ids.h -@@ -103,6 +103,9 @@ - #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 - #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 - #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 -+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 -+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 -+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 - #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 - #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a - #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b -@@ -466,6 +469,7 @@ - #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 - - #define USB_VENDOR_ID_ORTEK 0x05a4 -+#define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 - #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 - - #define USB_VENDOR_ID_PANJIT 0x134c ---- vanilla-2.6.38.0.orig/drivers/hid/hid-ortek.c -+++ vanilla-2.6.38.0/drivers/hid/hid-ortek.c -@@ -1,5 +1,5 @@ - /* -- * HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad). -+ * HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad). - * Fixes LogicalMaximum error in USB report description, see - * http://bugzilla.kernel.org/show_bug.cgi?id=14787 - * -@@ -30,6 +30,7 @@ static __u8 *ortek_report_fixup(struct h - } - - static const struct hid_device_id ortek_devices[] = { -+ { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { } - }; ---- vanilla-2.6.38.0.orig/drivers/pci/quirks.c -+++ vanilla-2.6.38.0/drivers/pci/quirks.c -@@ -533,6 +533,17 @@ static void __devinit quirk_piix4_acpi(s - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi); - -+#define ICH_PMBASE 0x40 -+#define ICH_ACPI_CNTL 0x44 -+#define ICH4_ACPI_EN 0x10 -+#define ICH6_ACPI_EN 0x80 -+#define ICH4_GPIOBASE 0x58 -+#define ICH4_GPIO_CNTL 0x5c -+#define ICH4_GPIO_EN 0x10 -+#define ICH6_GPIOBASE 0x48 -+#define ICH6_GPIO_CNTL 0x4c -+#define ICH6_GPIO_EN 0x10 -+ - /* - * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at - * 0x40 (128 bytes of ACPI, GPIO & TCO registers) -@@ -541,12 +552,33 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I - static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev) - { - u32 region; -+ u8 enable; - -- pci_read_config_dword(dev, 0x40, ®ion); -- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO"); -+ /* -+ * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict -+ * with low legacy (and fixed) ports. We don't know the decoding -+ * priority and can't tell whether the legacy device or the one created -+ * here is really at that address. This happens on boards with broken -+ * BIOSes. -+ */ -+ -+ pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); -+ if (enable & ICH4_ACPI_EN) { -+ pci_read_config_dword(dev, ICH_PMBASE, ®ion); -+ region &= PCI_BASE_ADDRESS_IO_MASK; -+ if (region >= PCIBIOS_MIN_IO) -+ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, -+ "ICH4 ACPI/GPIO/TCO"); -+ } - -- pci_read_config_dword(dev, 0x58, ®ion); -- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO"); -+ pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); -+ if (enable & ICH4_GPIO_EN) { -+ pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); -+ region &= PCI_BASE_ADDRESS_IO_MASK; -+ if (region >= PCIBIOS_MIN_IO) -+ quirk_io_region(dev, region, 64, -+ PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO"); -+ } - } - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi); -@@ -562,12 +594,25 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I - static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev) - { - u32 region; -+ u8 enable; - -- pci_read_config_dword(dev, 0x40, ®ion); -- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO"); -+ pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); -+ if (enable & ICH6_ACPI_EN) { -+ pci_read_config_dword(dev, ICH_PMBASE, ®ion); -+ region &= PCI_BASE_ADDRESS_IO_MASK; -+ if (region >= PCIBIOS_MIN_IO) -+ quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, -+ "ICH6 ACPI/GPIO/TCO"); -+ } - -- pci_read_config_dword(dev, 0x48, ®ion); -- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO"); -+ pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); -+ if (enable & ICH4_GPIO_EN) { -+ pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); -+ region &= PCI_BASE_ADDRESS_IO_MASK; -+ if (region >= PCIBIOS_MIN_IO) -+ quirk_io_region(dev, region, 64, -+ PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO"); -+ } - } - - static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) -@@ -2618,58 +2663,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT - - #endif /* CONFIG_PCI_MSI */ - --#ifdef CONFIG_PCI_IOV -- --/* -- * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the -- * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the -- * old Flash Memory Space. -- */ --static void __devinit quirk_i82576_sriov(struct pci_dev *dev) --{ -- int pos, flags; -- u32 bar, start, size; -- -- if (PAGE_SIZE > 0x10000) -- return; -- -- flags = pci_resource_flags(dev, 0); -- if ((flags & PCI_BASE_ADDRESS_SPACE) != -- PCI_BASE_ADDRESS_SPACE_MEMORY || -- (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != -- PCI_BASE_ADDRESS_MEM_TYPE_32) -- return; -- -- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); -- if (!pos) -- return; -- -- pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar); -- if (bar & PCI_BASE_ADDRESS_MEM_MASK) -- return; -- -- start = pci_resource_start(dev, 1); -- size = pci_resource_len(dev, 1); -- if (!start || size != 0x400000 || start & (size - 1)) -- return; -- -- pci_resource_flags(dev, 1) = 0; -- pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0); -- pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start); -- pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2); -- -- dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n"); --} --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); -- --#endif /* CONFIG_PCI_IOV */ -- - /* Allow manual resource allocation for PCI hotplug bridges - * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For - * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6), ---- vanilla-2.6.38.0.orig/drivers/pci/pci-sysfs.c -+++ vanilla-2.6.38.0/drivers/pci/pci-sysfs.c -@@ -1088,7 +1088,7 @@ static int pci_create_capabilities_sysfs - attr->write = write_vpd_attr; - retval = sysfs_create_bin_file(&dev->dev.kobj, attr); - if (retval) { -- kfree(dev->vpd->attr); -+ kfree(attr); - return retval; - } - dev->vpd->attr = attr; ---- vanilla-2.6.38.0.orig/sound/pci/asihpi/hpioctl.c -+++ vanilla-2.6.38.0/sound/pci/asihpi/hpioctl.c -@@ -155,6 +155,11 @@ long asihpi_hpi_ioctl(struct file *file, - goto out; - } - -+ if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) { -+ err = -EINVAL; -+ goto out; -+ } -+ - pa = &adapters[hm->h.adapter_index]; - hr->h.size = 0; - if (hm->h.object == HPI_OBJ_SUBSYSTEM) { ---- vanilla-2.6.38.0.orig/sound/drivers/aloop.c -+++ vanilla-2.6.38.0/sound/drivers/aloop.c -@@ -482,8 +482,9 @@ static unsigned int loopback_pos_update( - cable->streams[SNDRV_PCM_STREAM_CAPTURE]; - unsigned long delta_play = 0, delta_capt = 0; - unsigned int running; -+ unsigned long flags; - -- spin_lock(&cable->lock); -+ spin_lock_irqsave(&cable->lock, flags); - running = cable->running ^ cable->pause; - if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { - delta_play = jiffies - dpcm_play->last_jiffies; -@@ -495,10 +496,8 @@ static unsigned int loopback_pos_update( - dpcm_capt->last_jiffies += delta_capt; - } - -- if (delta_play == 0 && delta_capt == 0) { -- spin_unlock(&cable->lock); -- return running; -- } -+ if (delta_play == 0 && delta_capt == 0) -+ goto unlock; - - if (delta_play > delta_capt) { - loopback_bytepos_update(dpcm_play, delta_play - delta_capt, -@@ -510,14 +509,14 @@ static unsigned int loopback_pos_update( - delta_capt = delta_play; - } - -- if (delta_play == 0 && delta_capt == 0) { -- spin_unlock(&cable->lock); -- return running; -- } -+ if (delta_play == 0 && delta_capt == 0) -+ goto unlock; -+ - /* note delta_capt == delta_play at this moment */ - loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); - loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); -- spin_unlock(&cable->lock); -+ unlock: -+ spin_unlock_irqrestore(&cable->lock, flags); - return running; - } - ---- vanilla-2.6.38.0.orig/sound/pci/ctxfi/ctatc.c -+++ vanilla-2.6.38.0/sound/pci/ctxfi/ctatc.c -@@ -869,7 +869,7 @@ spdif_passthru_playback_setup(struct ct_ - mutex_lock(&atc->atc_mutex); - dao->ops->get_spos(dao, &status); - if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { -- status &= ((~IEC958_AES3_CON_FS) << 24); -+ status &= ~(IEC958_AES3_CON_FS << 24); - status |= (iec958_con_fs << 24); - dao->ops->set_spos(dao, status); - dao->ops->commit_write(dao); ---- vanilla-2.6.38.0.orig/sound/pci/ctxfi/ctmixer.c -+++ vanilla-2.6.38.0/sound/pci/ctxfi/ctmixer.c -@@ -566,19 +566,6 @@ static int ct_spdif_get_mask(struct snd_ - return 0; - } - --static int ct_spdif_default_get(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) --{ -- unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF; -- -- ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; -- ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; -- ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; -- ucontrol->value.iec958.status[3] = (status >> 24) & 0xff; -- -- return 0; --} -- - static int ct_spdif_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) - { -@@ -586,6 +573,10 @@ static int ct_spdif_get(struct snd_kcont - unsigned int status; - - atc->spdif_out_get_status(atc, &status); -+ -+ if (status == 0) -+ status = SNDRV_PCM_DEFAULT_CON_SPDIF; -+ - ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; - ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; - ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; -@@ -629,7 +620,7 @@ static struct snd_kcontrol_new iec958_de - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .count = 1, - .info = ct_spdif_info, -- .get = ct_spdif_default_get, -+ .get = ct_spdif_get, - .put = ct_spdif_put, - .private_value = MIXER_IEC958_DEFAULT - }; ---- vanilla-2.6.38.0.orig/sound/pci/ctxfi/ctdaio.c -+++ vanilla-2.6.38.0/sound/pci/ctxfi/ctdaio.c -@@ -176,6 +176,7 @@ static int dao_set_left_input(struct dao - if (!entry) - return -ENOMEM; - -+ dao->ops->clear_left_input(dao); - /* Program master and conjugate resources */ - input->ops->master(input); - daio->rscl.ops->master(&daio->rscl); -@@ -204,6 +205,7 @@ static int dao_set_right_input(struct da - if (!entry) - return -ENOMEM; - -+ dao->ops->clear_right_input(dao); - /* Program master and conjugate resources */ - input->ops->master(input); - daio->rscr.ops->master(&daio->rscr); ---- vanilla-2.6.38.0.orig/sound/soc/pxa/z2.c -+++ vanilla-2.6.38.0/sound/soc/pxa/z2.c -@@ -147,7 +147,7 @@ static int z2_wm8750_init(struct snd_soc - snd_soc_dapm_disable_pin(dapm, "LINPUT3"); - snd_soc_dapm_disable_pin(dapm, "RINPUT3"); - snd_soc_dapm_disable_pin(dapm, "OUT3"); -- snd_soc_dapm_disable_pin(dapm, "MONO"); -+ snd_soc_dapm_disable_pin(dapm, "MONO1"); - - /* Add z2 specific widgets */ - snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets, ---- vanilla-2.6.38.0.orig/drivers/target/target_core_cdb.c -+++ vanilla-2.6.38.0/drivers/target/target_core_cdb.c -@@ -667,7 +667,13 @@ target_emulate_readcapacity(struct se_cm - { - struct se_device *dev = SE_DEV(cmd); - unsigned char *buf = cmd->t_task->t_task_buf; -- u32 blocks = dev->transport->get_blocks(dev); -+ unsigned long long blocks_long = dev->transport->get_blocks(dev); -+ u32 blocks; -+ -+ if (blocks_long >= 0x00000000ffffffff) -+ blocks = 0xffffffff; -+ else -+ blocks = (u32)blocks_long; - - buf[0] = (blocks >> 24) & 0xff; - buf[1] = (blocks >> 16) & 0xff; ---- vanilla-2.6.38.0.orig/drivers/scsi/device_handler/scsi_dh_alua.c -+++ vanilla-2.6.38.0/drivers/scsi/device_handler/scsi_dh_alua.c -@@ -285,7 +285,8 @@ static void stpg_endio(struct request *r - print_alua_state(h->state)); - } - done: -- blk_put_request(req); -+ req->end_io_data = NULL; -+ __blk_put_request(req->q, req); - if (h->callback_fn) { - h->callback_fn(h->callback_data, err); - h->callback_fn = h->callback_data = NULL; ---- vanilla-2.6.38.0.orig/net/sunrpc/sched.c -+++ vanilla-2.6.38.0/net/sunrpc/sched.c -@@ -637,14 +637,12 @@ static void __rpc_execute(struct rpc_tas - save_callback = task->tk_callback; - task->tk_callback = NULL; - save_callback(task); -- } -- -- /* -- * Perform the next FSM step. -- * tk_action may be NULL when the task has been killed -- * by someone else. -- */ -- if (!RPC_IS_QUEUED(task)) { -+ } else { -+ /* -+ * Perform the next FSM step. -+ * tk_action may be NULL when the task has been killed -+ * by someone else. -+ */ - if (task->tk_action == NULL) - break; - task->tk_action(task); ---- vanilla-2.6.38.0.orig/net/sunrpc/clnt.c -+++ vanilla-2.6.38.0/net/sunrpc/clnt.c -@@ -436,7 +436,9 @@ void rpc_killall_tasks(struct rpc_clnt * - if (!(rovr->tk_flags & RPC_TASK_KILLED)) { - rovr->tk_flags |= RPC_TASK_KILLED; - rpc_exit(rovr, -EIO); -- rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr); -+ if (RPC_IS_QUEUED(rovr)) -+ rpc_wake_up_queued_task(rovr->tk_waitqueue, -+ rovr); - } - } - spin_unlock(&clnt->cl_lock); ---- vanilla-2.6.38.0.orig/kernel/perf_event.c -+++ vanilla-2.6.38.0/kernel/perf_event.c -@@ -4567,7 +4567,7 @@ static int perf_exclude_event(struct per - struct pt_regs *regs) - { - if (event->hw.state & PERF_HES_STOPPED) -- return 0; -+ return 1; - - if (regs) { - if (event->attr.exclude_user && user_mode(regs)) -@@ -4923,6 +4923,8 @@ static int perf_tp_event_match(struct pe - struct perf_sample_data *data, - struct pt_regs *regs) - { -+ if (event->hw.state & PERF_HES_STOPPED) -+ return 0; - /* - * All tracepoints are from kernel-space. - */ ---- vanilla-2.6.38.0.orig/arch/powerpc/include/asm/reg.h -+++ vanilla-2.6.38.0/arch/powerpc/include/asm/reg.h -@@ -880,6 +880,7 @@ - #define PV_970 0x0039 - #define PV_POWER5 0x003A - #define PV_POWER5p 0x003B -+#define PV_POWER7 0x003F - #define PV_970FX 0x003C - #define PV_630 0x0040 - #define PV_630p 0x0041 ---- vanilla-2.6.38.0.orig/arch/powerpc/kernel/perf_event.c -+++ vanilla-2.6.38.0/arch/powerpc/kernel/perf_event.c -@@ -1269,6 +1269,28 @@ unsigned long perf_instruction_pointer(s - return ip; - } - -+static bool pmc_overflow(unsigned long val) -+{ -+ if ((int)val < 0) -+ return true; -+ -+ /* -+ * Events on POWER7 can roll back if a speculative event doesn't -+ * eventually complete. Unfortunately in some rare cases they will -+ * raise a performance monitor exception. We need to catch this to -+ * ensure we reset the PMC. In all cases the PMC will be 256 or less -+ * cycles from overflow. -+ * -+ * We only do this if the first pass fails to find any overflowing -+ * PMCs because a user might set a period of less than 256 and we -+ * don't want to mistakenly reset them. -+ */ -+ if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) -+ return true; -+ -+ return false; -+} -+ - /* - * Performance monitor interrupt stuff - */ -@@ -1316,7 +1338,7 @@ static void perf_event_interrupt(struct - if (is_limited_pmc(i + 1)) - continue; - val = read_pmc(i + 1); -- if ((int)val < 0) -+ if (pmc_overflow(val)) - write_pmc(i + 1, 0); - } - } ---- vanilla-2.6.38.0.orig/tools/perf/util/PERF-VERSION-GEN -+++ vanilla-2.6.38.0/tools/perf/util/PERF-VERSION-GEN -@@ -23,10 +23,10 @@ if test -d ../../.git -o -f ../../.git & - then - VN=$(echo "$VN" | sed -e 's/-/./g'); - else -- eval `grep '^VERSION\s*=' ../../Makefile|tr -d ' '` -- eval `grep '^PATCHLEVEL\s*=' ../../Makefile|tr -d ' '` -- eval `grep '^SUBLEVEL\s*=' ../../Makefile|tr -d ' '` -- eval `grep '^EXTRAVERSION\s*=' ../../Makefile|tr -d ' '` -+ eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ') -+ eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') -+ eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') -+ eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ') - - VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}" - fi ---- vanilla-2.6.38.0.orig/fs/ext3/namei.c -+++ vanilla-2.6.38.0/fs/ext3/namei.c -@@ -1540,8 +1540,8 @@ static int ext3_dx_add_entry(handle_t *h - goto cleanup; - node2 = (struct dx_node *)(bh2->b_data); - entries2 = node2->entries; -+ memset(&node2->fake, 0, sizeof(struct fake_dirent)); - node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize); -- node2->fake.inode = 0; - BUFFER_TRACE(frame->bh, "get_write_access"); - err = ext3_journal_get_write_access(handle, frame->bh); - if (err) ---- vanilla-2.6.38.0.orig/kernel/smp.c -+++ vanilla-2.6.38.0/kernel/smp.c -@@ -450,7 +450,7 @@ void smp_call_function_many(const struct - { - struct call_function_data *data; - unsigned long flags; -- int cpu, next_cpu, this_cpu = smp_processor_id(); -+ int refs, cpu, next_cpu, this_cpu = smp_processor_id(); - - /* - * Can deadlock when called with interrupts disabled. -@@ -461,7 +461,7 @@ void smp_call_function_many(const struct - WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled() - && !oops_in_progress && !early_boot_irqs_disabled); - -- /* So, what's a CPU they want? Ignoring this one. */ -+ /* Try to fastpath. So, what's a CPU they want? Ignoring this one. */ - cpu = cpumask_first_and(mask, cpu_online_mask); - if (cpu == this_cpu) - cpu = cpumask_next_and(cpu, mask, cpu_online_mask); -@@ -483,22 +483,49 @@ void smp_call_function_many(const struct - - data = &__get_cpu_var(cfd_data); - csd_lock(&data->csd); -+ -+ /* This BUG_ON verifies our reuse assertions and can be removed */ - BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask)); - -+ /* -+ * The global call function queue list add and delete are protected -+ * by a lock, but the list is traversed without any lock, relying -+ * on the rcu list add and delete to allow safe concurrent traversal. -+ * We reuse the call function data without waiting for any grace -+ * period after some other cpu removes it from the global queue. -+ * This means a cpu might find our data block as it is being -+ * filled out. -+ * -+ * We hold off the interrupt handler on the other cpu by -+ * ordering our writes to the cpu mask vs our setting of the -+ * refs counter. We assert only the cpu owning the data block -+ * will set a bit in cpumask, and each bit will only be cleared -+ * by the subject cpu. Each cpu must first find its bit is -+ * set and then check that refs is set indicating the element is -+ * ready to be processed, otherwise it must skip the entry. -+ * -+ * On the previous iteration refs was set to 0 by another cpu. -+ * To avoid the use of transitivity, set the counter to 0 here -+ * so the wmb will pair with the rmb in the interrupt handler. -+ */ -+ atomic_set(&data->refs, 0); /* convert 3rd to 1st party write */ -+ - data->csd.func = func; - data->csd.info = info; -- cpumask_and(data->cpumask, mask, cpu_online_mask); -- cpumask_clear_cpu(this_cpu, data->cpumask); - -- /* -- * To ensure the interrupt handler gets an complete view -- * we order the cpumask and refs writes and order the read -- * of them in the interrupt handler. In addition we may -- * only clear our own cpu bit from the mask. -- */ -+ /* Ensure 0 refs is visible before mask. Also orders func and info */ - smp_wmb(); - -- atomic_set(&data->refs, cpumask_weight(data->cpumask)); -+ /* We rely on the "and" being processed before the store */ -+ cpumask_and(data->cpumask, mask, cpu_online_mask); -+ cpumask_clear_cpu(this_cpu, data->cpumask); -+ refs = cpumask_weight(data->cpumask); -+ -+ /* Some callers race with other cpus changing the passed mask */ -+ if (unlikely(!refs)) { -+ csd_unlock(&data->csd); -+ return; -+ } - - raw_spin_lock_irqsave(&call_function.lock, flags); - /* -@@ -507,6 +534,12 @@ void smp_call_function_many(const struct - * will not miss any other list entries: - */ - list_add_rcu(&data->csd.list, &call_function.queue); -+ /* -+ * We rely on the wmb() in list_add_rcu to complete our writes -+ * to the cpumask before this write to refs, which indicates -+ * data is on the list and is ready to be processed. -+ */ -+ atomic_set(&data->refs, refs); - raw_spin_unlock_irqrestore(&call_function.lock, flags); - - /* ---- vanilla-2.6.38.0.orig/arch/x86/include/asm/pgtable-3level.h -+++ vanilla-2.6.38.0/arch/x86/include/asm/pgtable-3level.h -@@ -69,8 +69,6 @@ static inline void native_pmd_clear(pmd_ - - static inline void pud_clear(pud_t *pudp) - { -- unsigned long pgd; -- - set_pud(pudp, __pud(0)); - - /* -@@ -79,13 +77,10 @@ static inline void pud_clear(pud_t *pudp - * section 8.1: in PAE mode we explicitly have to flush the - * TLB via cr3 if the top-level pgd is changed... - * -- * Make sure the pud entry we're updating is within the -- * current pgd to avoid unnecessary TLB flushes. -+ * Currently all places where pud_clear() is called either have -+ * flush_tlb_mm() followed or don't need TLB flush (x86_64 code or -+ * pud_clear_bad()), so we don't need TLB flush here. - */ -- pgd = read_cr3(); -- if (__pa(pudp) >= pgd && __pa(pudp) < -- (pgd + sizeof(pgd_t)*PTRS_PER_PGD)) -- write_cr3(pgd); - } - - #ifdef CONFIG_SMP ---- vanilla-2.6.38.0.orig/arch/x86/mm/pgtable.c -+++ vanilla-2.6.38.0/arch/x86/mm/pgtable.c -@@ -168,8 +168,7 @@ void pud_populate(struct mm_struct *mm, - * section 8.1: in PAE mode we explicitly have to flush the - * TLB via cr3 if the top-level pgd is changed... - */ -- if (mm == current->active_mm) -- write_cr3(read_cr3()); -+ flush_tlb_mm(mm); - } - #else /* !CONFIG_X86_PAE */ - ---- vanilla-2.6.38.0.orig/drivers/hid/Makefile -+++ vanilla-2.6.38.0/drivers/hid/Makefile -@@ -27,7 +27,7 @@ endif - - obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o - obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o --obj-$(CONFIG_HID_ACRUX_FF) += hid-axff.o -+obj-$(CONFIG_HID_ACRUX) += hid-axff.o - obj-$(CONFIG_HID_APPLE) += hid-apple.o - obj-$(CONFIG_HID_BELKIN) += hid-belkin.o - obj-$(CONFIG_HID_CANDO) += hid-cando.o ---- vanilla-2.6.38.0.orig/drivers/hid/hid-axff.c -+++ vanilla-2.6.38.0/drivers/hid/hid-axff.c -@@ -33,6 +33,8 @@ - #include - - #include "hid-ids.h" -+ -+#ifdef CONFIG_HID_ACRUX_FF - #include "usbhid/usbhid.h" - - struct axff_device { -@@ -109,6 +111,12 @@ err_free_mem: - kfree(axff); - return error; - } -+#else -+static inline int axff_init(struct hid_device *hid) -+{ -+ return 0; -+} -+#endif - - static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) - { -@@ -139,9 +147,25 @@ static int ax_probe(struct hid_device *h - error); - } - -+ /* -+ * We need to start polling device right away, otherwise -+ * it will go into a coma. -+ */ -+ error = hid_hw_open(hdev); -+ if (error) { -+ dev_err(&hdev->dev, "hw open failed\n"); -+ return error; -+ } -+ - return 0; - } - -+static void ax_remove(struct hid_device *hdev) -+{ -+ hid_hw_close(hdev); -+ hid_hw_stop(hdev); -+} -+ - static const struct hid_device_id ax_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, - { } -@@ -149,9 +173,10 @@ static const struct hid_device_id ax_dev - MODULE_DEVICE_TABLE(hid, ax_devices); - - static struct hid_driver ax_driver = { -- .name = "acrux", -- .id_table = ax_devices, -- .probe = ax_probe, -+ .name = "acrux", -+ .id_table = ax_devices, -+ .probe = ax_probe, -+ .remove = ax_remove, - }; - - static int __init ax_init(void) ---- vanilla-2.6.38.0.orig/drivers/hid/hid-input.c -+++ vanilla-2.6.38.0/drivers/hid/hid-input.c -@@ -290,14 +290,6 @@ static void hidinput_configure_usage(str - goto ignore; - } - -- if (field->report_type == HID_FEATURE_REPORT) { -- if (device->driver->feature_mapping) { -- device->driver->feature_mapping(device, hidinput, field, -- usage); -- } -- goto ignore; -- } -- - if (device->driver->input_mapping) { - int ret = device->driver->input_mapping(device, hidinput, field, - usage, &bit, &max); -@@ -835,6 +827,24 @@ static void hidinput_close(struct input_ - hid_hw_close(hid); - } - -+static void report_features(struct hid_device *hid) -+{ -+ struct hid_driver *drv = hid->driver; -+ struct hid_report_enum *rep_enum; -+ struct hid_report *rep; -+ int i, j; -+ -+ if (!drv->feature_mapping) -+ return; -+ -+ rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; -+ list_for_each_entry(rep, &rep_enum->report_list, list) -+ for (i = 0; i < rep->maxfield; i++) -+ for (j = 0; j < rep->field[i]->maxusage; j++) -+ drv->feature_mapping(hid, rep->field[i], -+ rep->field[i]->usage + j); -+} -+ - /* - * Register the input device; print a message. - * Configure the input layer interface -@@ -863,7 +873,9 @@ int hidinput_connect(struct hid_device * - return -1; - } - -- for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) { -+ report_features(hid); -+ -+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { - if (k == HID_OUTPUT_REPORT && - hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) - continue; ---- vanilla-2.6.38.0.orig/drivers/hid/hid-multitouch.c -+++ vanilla-2.6.38.0/drivers/hid/hid-multitouch.c -@@ -122,7 +122,7 @@ struct mt_class mt_classes[] = { - { } - }; - --static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi, -+static void mt_feature_mapping(struct hid_device *hdev, - struct hid_field *field, struct hid_usage *usage) - { - if (usage->hid == HID_DG_INPUTMODE) { ---- vanilla-2.6.38.0.orig/include/linux/hid.h -+++ vanilla-2.6.38.0/include/linux/hid.h -@@ -638,7 +638,7 @@ struct hid_driver { - struct hid_input *hidinput, struct hid_field *field, - struct hid_usage *usage, unsigned long **bit, int *max); - void (*feature_mapping)(struct hid_device *hdev, -- struct hid_input *hidinput, struct hid_field *field, -+ struct hid_field *field, - struct hid_usage *usage); - #ifdef CONFIG_PM - int (*suspend)(struct hid_device *hdev, pm_message_t message); ---- vanilla-2.6.38.0.orig/arch/parisc/kernel/irq.c -+++ vanilla-2.6.38.0/arch/parisc/kernel/irq.c -@@ -108,7 +108,7 @@ int cpu_check_affinity(unsigned int irq, - int cpu_dest; - - /* timer and ipi have to always be received on all CPUs */ -- if (CHECK_IRQ_PER_CPU(irq)) { -+ if (CHECK_IRQ_PER_CPU(irq_to_desc(irq)->status)) { - /* Bad linux design decision. The mask has already - * been set; we must reset it */ - cpumask_setall(irq_desc[irq].affinity); ---- vanilla-2.6.38.0.orig/drivers/hid/hid-apple.c -+++ vanilla-2.6.38.0/drivers/hid/hid-apple.c -@@ -481,6 +481,12 @@ static const struct hid_device_id apple_ - .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), - .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), -+ .driver_data = APPLE_HAS_FN }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), -+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), -+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), - .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), ---- vanilla-2.6.38.0.orig/drivers/input/mouse/bcm5974.c -+++ vanilla-2.6.38.0/drivers/input/mouse/bcm5974.c -@@ -63,6 +63,10 @@ - #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 - #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 - #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 -+/* Macbook8 (unibody, March 2011) */ -+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 -+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 -+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 - - #define BCM5974_DEVICE(prod) { \ - .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ -@@ -96,6 +100,10 @@ static const struct usb_device_id bcm597 - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), - BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), -+ /* MacbookPro8 */ -+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), -+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), -+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), - /* Terminating entry */ - {} - }; -@@ -274,6 +282,18 @@ static const struct bcm5974_config bcm59 - { DIM_X, DIM_X / SN_COORD, -4616, 5112 }, - { DIM_Y, DIM_Y / SN_COORD, -142, 5234 } - }, -+ { -+ USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, -+ USB_DEVICE_ID_APPLE_WELLSPRING5_ISO, -+ USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, -+ HAS_INTEGRATED_BUTTON, -+ 0x84, sizeof(struct bt_data), -+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, -+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, -+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, -+ { DIM_X, DIM_X / SN_COORD, -4415, 5050 }, -+ { DIM_Y, DIM_Y / SN_COORD, -55, 6680 } -+ }, - {} - }; - ---- vanilla-2.6.38.0.orig/Documentation/i2c/instantiating-devices -+++ vanilla-2.6.38.0/Documentation/i2c/instantiating-devices -@@ -100,7 +100,7 @@ static int __devinit usb_hcd_pnx4008_pro - (...) - i2c_adap = i2c_get_adapter(2); - memset(&i2c_info, 0, sizeof(struct i2c_board_info)); -- strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); -+ strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE); - isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, - normal_i2c, NULL); - i2c_put_adapter(i2c_adap); ---- vanilla-2.6.38.0.orig/drivers/mmc/host/sdhci-pci.c -+++ vanilla-2.6.38.0/drivers/mmc/host/sdhci-pci.c -@@ -547,6 +547,14 @@ static const struct pci_device_id pci_id - }, - - { -+ .vendor = PCI_VENDOR_ID_RICOH, -+ .device = 0xe823, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID, -+ .driver_data = (kernel_ulong_t)&sdhci_ricoh_mmc, -+ }, -+ -+ { - .vendor = PCI_VENDOR_ID_ENE, - .device = PCI_DEVICE_ID_ENE_CB712_SD, - .subvendor = PCI_ANY_ID, ---- vanilla-2.6.38.0.orig/drivers/mmc/core/sdio.c -+++ vanilla-2.6.38.0/drivers/mmc/core/sdio.c -@@ -395,6 +395,14 @@ static int mmc_sdio_init_card(struct mmc - if (err) - goto remove; - -+ /* -+ * Update oldcard with the new RCA received from the SDIO -+ * device -- we're doing this so that it's updated in the -+ * "card" struct when oldcard overwrites that later. -+ */ -+ if (oldcard) -+ oldcard->rca = card->rca; -+ - mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); - } - ---- vanilla-2.6.38.0.orig/arch/x86/kernel/entry_64.S -+++ vanilla-2.6.38.0/arch/x86/kernel/entry_64.S -@@ -1248,7 +1248,7 @@ ENTRY(xen_do_hypervisor_callback) # do - decl PER_CPU_VAR(irq_count) - jmp error_exit - CFI_ENDPROC --END(do_hypervisor_callback) -+END(xen_do_hypervisor_callback) - - /* - * Hypervisor uses this for application faults while it executes. ---- vanilla-2.6.38.0.orig/arch/arm/mach-davinci/board-dm644x-evm.c -+++ vanilla-2.6.38.0/arch/arm/mach-davinci/board-dm644x-evm.c -@@ -440,11 +440,6 @@ evm_u35_setup(struct i2c_client *client, - gpio_request(gpio + 7, "nCF_SEL"); - gpio_direction_output(gpio + 7, 1); - -- /* irlml6401 switches over 1A, in under 8 msec; -- * now it can be managed by nDRV_VBUS ... -- */ -- davinci_setup_usb(1000, 8); -- - return 0; - } - -@@ -705,6 +700,9 @@ static __init void davinci_evm_init(void - davinci_serial_init(&uart_config); - dm644x_init_asp(&dm644x_evm_snd_data); - -+ /* irlml6401 switches over 1A, in under 8 msec */ -+ davinci_setup_usb(1000, 8); -+ - soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID; - /* Register the fixup for PHY on DaVinci */ - phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, ---- vanilla-2.6.38.0.orig/drivers/hwmon/sht15.c -+++ vanilla-2.6.38.0/drivers/hwmon/sht15.c -@@ -333,11 +333,11 @@ static inline int sht15_calc_humid(struc - - const int c1 = -4; - const int c2 = 40500; /* x 10 ^ -6 */ -- const int c3 = -2800; /* x10 ^ -9 */ -+ const int c3 = -28; /* x 10 ^ -7 */ - - RHlinear = c1*1000 - + c2 * data->val_humid/1000 -- + (data->val_humid * data->val_humid * c3)/1000000; -+ + (data->val_humid * data->val_humid * c3) / 10000; - return (temp - 25000) * (10000 + 80 * data->val_humid) - / 1000000 + RHlinear; - } diff --git a/kernel.spec b/kernel.spec index e40bf2b2f..405c30c27 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 5 +%global baserelease 6 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,7 +63,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 0 +%define stable_update 1 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -727,7 +727,6 @@ Patch12102: efifb_update.patch Patch12200: acpi_reboot.patch # Runtime power management -Patch12202: linux-2.6-ehci-check-port-status.patch Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12205: runtime_pm_fixups.patch @@ -736,6 +735,9 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch12421: fs-call-security_d_instantiate-in-d_obtain_alias.patch +# Fix possible memory corruption on Dell HW +Patch12430: dcdbas-force-smi-to-happen-when-expected.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1356,7 +1358,6 @@ ApplyPatch efifb_update.patch ApplyPatch acpi_reboot.patch # Runtime PM -#ApplyPatch linux-2.6-ehci-check-port-status.patch #ApplyPatch linux-2.6-usb-pci-autosuspend.patch ### Broken by implicit notify support & ACPICA rebase ###ApplyPatch linux-2.6-enable-more-pci-autosuspend.patch @@ -1368,6 +1369,9 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch # rhbz#662344,600690 ApplyPatch fs-call-security_d_instantiate-in-d_obtain_alias.patch +# Fix possible memory corruption on Dell HW +ApplyPatch dcdbas-force-smi-to-happen-when-expected.patch + # END OF PATCH APPLICATIONS %endif @@ -1976,6 +1980,11 @@ fi # and build. %changelog +* Wed Mar 23 2011 Chuck Ebbert 2.6.38.1-6 +- Linux 2.6.38.1 +- Drop linux-2.6-ehci-check-port-status.patch, merged in .38.1 +- Add dcdbas-force-smi-to-happen-when-expected.patch + * Wed Mar 23 2011 Kyle McMartin - Re-create ACPI battery sysfs files on resume from suspend, fixes the upstream changes to the dropped diff --git a/linux-2.6-ehci-check-port-status.patch b/linux-2.6-ehci-check-port-status.patch deleted file mode 100644 index f3c5faf70..000000000 --- a/linux-2.6-ehci-check-port-status.patch +++ /dev/null @@ -1,54 +0,0 @@ -commit e17a07a9e0b62d5a5f0a5683ecbabad3aa95a4d5 -Author: Matthew Garrett -Date: Tue Jan 11 12:19:40 2011 -0500 - - ehci: Check individual port status registers on resume - - If a device plug/unplug is detected on an ATI SB700 USB controller in D3, - it appears to set the port status register but not the controller status - register. As a result we'll fail to detect the plug event. Check the port - status register on resume as well in order to catch this case. - - Signed-off-by: Matthew Garrett - -diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c -index 796ea0c..d9c0748 100644 ---- a/drivers/usb/host/ehci-hub.c -+++ b/drivers/usb/host/ehci-hub.c -@@ -106,6 +106,27 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) - ehci->owned_ports = 0; - } - -+static int ehci_port_change(struct ehci_hcd *ehci) -+{ -+ int i = HCS_N_PORTS(ehci->hcs_params); -+ -+ /* First check if the controller indicates a change event */ -+ -+ if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD) -+ return 1; -+ -+ /* -+ * Not all controllers appear to update this while going from D3 to D0, -+ * so check the individual port status registers as well -+ */ -+ -+ while (i--) -+ if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC) -+ return 1; -+ -+ return 0; -+} -+ - static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, - bool suspending, bool do_wakeup) - { -@@ -168,7 +189,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, - } - - /* Does the root hub have a port wakeup pending? */ -- if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)) -+ if (!suspending && ehci_port_change(ehci)) - usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); - - spin_unlock_irqrestore(&ehci->lock, flags); diff --git a/sources b/sources index a051716d2..69531329e 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 +bd2be4d0465345e4e9355d6773f5f6fe patch-2.6.38.1.bz2 From 06ad6a4c25545784308248db8cabb417adf160ed Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 25 Mar 2011 10:15:57 -0400 Subject: [PATCH 08/99] CVE-2011-1182: kernel signal spoofing issue --- kernel.spec | 11 +++- ...ueinfo-from-spoofing-the-signal-code.patch | 64 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch diff --git a/kernel.spec b/kernel.spec index 405c30c27..1a358321e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 6 +%global baserelease 7 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -738,6 +738,9 @@ Patch12421: fs-call-security_d_instantiate-in-d_obtain_alias.patch # Fix possible memory corruption on Dell HW Patch12430: dcdbas-force-smi-to-happen-when-expected.patch +# CVE-2011-1182 +Patch12431: prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1372,6 +1375,9 @@ ApplyPatch fs-call-security_d_instantiate-in-d_obtain_alias.patch # Fix possible memory corruption on Dell HW ApplyPatch dcdbas-force-smi-to-happen-when-expected.patch +# CVE-2011-1182 +ApplyPatch prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch + # END OF PATCH APPLICATIONS %endif @@ -1980,6 +1986,9 @@ fi # and build. %changelog +* Fri Mar 25 2011 Chuck Ebbert +- CVE-2011-1182: kernel signal spoofing issue + * Wed Mar 23 2011 Chuck Ebbert 2.6.38.1-6 - Linux 2.6.38.1 - Drop linux-2.6-ehci-check-port-status.patch, merged in .38.1 diff --git a/prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch b/prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch new file mode 100644 index 000000000..747a0e330 --- /dev/null +++ b/prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch @@ -0,0 +1,64 @@ +From: Julien Tinnes +Date: Fri, 18 Mar 2011 22:05:21 +0000 (-0700) +Subject: Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal code +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=da48524eb20662618854bb3df2db01fc65f3070c + +Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal code + +Userland should be able to trust the pid and uid of the sender of a +signal if the si_code is SI_TKILL. + +Unfortunately, the kernel has historically allowed sigqueueinfo() to +send any si_code at all (as long as it was negative - to distinguish it +from kernel-generated signals like SIGILL etc), so it could spoof a +SI_TKILL with incorrect siginfo values. + +Happily, it looks like glibc has always set si_code to the appropriate +SI_QUEUE, so there are probably no actual user code that ever uses +anything but the appropriate SI_QUEUE flag. + +So just tighten the check for si_code (we used to allow any negative +value), and add a (one-time) warning in case there are binaries out +there that might depend on using other si_code values. + +Signed-off-by: Julien Tinnes +Acked-by: Oleg Nesterov +Signed-off-by: Linus Torvalds +--- + +diff --git a/kernel/signal.c b/kernel/signal.c +index 4e3cff1..3175186 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2421,9 +2421,13 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, + return -EFAULT; + + /* Not even root can pretend to send signals from the kernel. +- Nor can they impersonate a kill(), which adds source info. */ +- if (info.si_code >= 0) ++ * Nor can they impersonate a kill()/tgkill(), which adds source info. ++ */ ++ if (info.si_code != SI_QUEUE) { ++ /* We used to allow any < 0 si_code */ ++ WARN_ON_ONCE(info.si_code < 0); + return -EPERM; ++ } + info.si_signo = sig; + + /* POSIX.1b doesn't mention process groups. */ +@@ -2437,9 +2441,13 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) + return -EINVAL; + + /* Not even root can pretend to send signals from the kernel. +- Nor can they impersonate a kill(), which adds source info. */ +- if (info->si_code >= 0) ++ * Nor can they impersonate a kill()/tgkill(), which adds source info. ++ */ ++ if (info->si_code != SI_QUEUE) { ++ /* We used to allow any < 0 si_code */ ++ WARN_ON_ONCE(info->si_code < 0); + return -EPERM; ++ } + info->si_signo = sig; + + return do_send_specific(tgid, pid, sig, info); From 535b4d942d610b2bbd5ec93c7441c0ca50ad06df Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 25 Mar 2011 17:54:00 -0400 Subject: [PATCH 09/99] Drop unused patches already applied upstream --- hdpvr-ir-enable.patch | 229 ------------------------------ kernel.spec | 9 +- thinkpad-acpi-fix-backlight.patch | 56 -------- 3 files changed, 3 insertions(+), 291 deletions(-) delete mode 100644 hdpvr-ir-enable.patch delete mode 100644 thinkpad-acpi-fix-backlight.patch diff --git a/hdpvr-ir-enable.patch b/hdpvr-ir-enable.patch deleted file mode 100644 index e73c42122..000000000 --- a/hdpvr-ir-enable.patch +++ /dev/null @@ -1,229 +0,0 @@ -diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile -index e0230fc..3baa9f6 100644 ---- a/drivers/media/video/hdpvr/Makefile -+++ b/drivers/media/video/hdpvr/Makefile -@@ -1,6 +1,4 @@ --hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o -- --hdpvr-$(CONFIG_I2C) += hdpvr-i2c.o -+hdpvr-objs := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o - - obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o - -diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c -index 830d47b..70cfdc8 100644 ---- a/drivers/media/video/hdpvr/hdpvr-core.c -+++ b/drivers/media/video/hdpvr/hdpvr-core.c -@@ -364,14 +364,13 @@ static int hdpvr_probe(struct usb_interface *interface, - goto error; - } - --#ifdef CONFIG_I2C -- /* until i2c is working properly */ -- retval = 0; /* hdpvr_register_i2c_adapter(dev); */ -+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -+ retval = hdpvr_register_i2c_adapter(dev); - if (retval < 0) { - v4l2_err(&dev->v4l2_dev, "registering i2c adapter failed\n"); - goto error; - } --#endif /* CONFIG_I2C */ -+#endif - - /* let the user know what node this device is now attached to */ - v4l2_info(&dev->v4l2_dev, "device now attached to %s\n", -diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c -index 463b81b..60cdc06 100644 ---- a/drivers/media/video/hdpvr/hdpvr-i2c.c -+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c -@@ -10,6 +10,8 @@ - * - */ - -+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -+ - #include - #include - -@@ -22,8 +24,11 @@ - #define REQTYPE_I2C_WRITE 0xb0 - #define REQTYPE_I2C_WRITE_STATT 0xd0 - --static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, -- char *data, int len) -+#define HDPVR_HW_Z8F0811_IR_TX_I2C_ADDR 0x70 -+#define HDPVR_HW_Z8F0811_IR_RX_I2C_ADDR 0x71 -+ -+static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, -+ unsigned char addr, char *data, int len) - { - int ret; - char *buf = kmalloc(len, GFP_KERNEL); -@@ -33,7 +38,7 @@ static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, - ret = usb_control_msg(dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - REQTYPE_I2C_READ, CTRL_READ_REQUEST, -- 0x100|addr, 0, buf, len, 1000); -+ (bus << 8) | addr, 0, buf, len, 1000); - - if (ret == len) { - memcpy(data, buf, len); -@@ -46,8 +51,8 @@ static int hdpvr_i2c_read(struct hdpvr_device *dev, unsigned char addr, - return ret; - } - --static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, -- char *data, int len) -+static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus, -+ unsigned char addr, char *data, int len) - { - int ret; - char *buf = kmalloc(len, GFP_KERNEL); -@@ -58,7 +63,7 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, -- 0x100|addr, 0, buf, len, 1000); -+ (bus << 8) | addr, 0, buf, len, 1000); - - if (ret < 0) - goto error; -@@ -68,7 +73,7 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, unsigned char addr, - REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, - 0, 0, buf, 2, 1000); - -- if (ret == 2) -+ if ((ret == 2) && (buf[1] == (len - 1))) - ret = 0; - else if (ret >= 0) - ret = -EIO; -@@ -93,10 +98,10 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, - addr = msgs[i].addr << 1; - - if (msgs[i].flags & I2C_M_RD) -- retval = hdpvr_i2c_read(dev, addr, msgs[i].buf, -+ retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf, - msgs[i].len); - else -- retval = hdpvr_i2c_write(dev, addr, msgs[i].buf, -+ retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf, - msgs[i].len); - } - -@@ -115,30 +120,58 @@ static struct i2c_algorithm hdpvr_algo = { - .functionality = hdpvr_functionality, - }; - -+static struct i2c_adapter hdpvr_i2c_adapter_template = { -+ .name = "Hauppage HD PVR I2C", -+ .owner = THIS_MODULE, -+ .id = I2C_HW_B_HDPVR, -+ .algo = &hdpvr_algo, -+}; -+ -+static struct i2c_board_info hdpvr_i2c_board_info = { -+ I2C_BOARD_INFO("ir_tx_z8f0811_haup", HDPVR_HW_Z8F0811_IR_TX_I2C_ADDR), -+ I2C_BOARD_INFO("ir_rx_z8f0811_haup", HDPVR_HW_Z8F0811_IR_RX_I2C_ADDR), -+}; -+ -+static int hdpvr_activate_ir(struct hdpvr_device *dev) -+{ -+ char buffer[8]; -+ -+ mutex_lock(&dev->i2c_mutex); -+ -+ hdpvr_i2c_read(dev, 0, 0x54, buffer, 1); -+ -+ buffer[0] = 0; -+ buffer[1] = 0x8; -+ hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); -+ -+ buffer[1] = 0x18; -+ hdpvr_i2c_write(dev, 1, 0x54, buffer, 2); -+ -+ mutex_unlock(&dev->i2c_mutex); -+ -+ return 0; -+} -+ - int hdpvr_register_i2c_adapter(struct hdpvr_device *dev) - { -- struct i2c_adapter *i2c_adap; - int retval = -ENOMEM; - -- i2c_adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); -- if (i2c_adap == NULL) -- goto error; -+ hdpvr_activate_ir(dev); - -- strlcpy(i2c_adap->name, "Hauppauge HD PVR I2C", -- sizeof(i2c_adap->name)); -- i2c_adap->algo = &hdpvr_algo; -- i2c_adap->owner = THIS_MODULE; -- i2c_adap->dev.parent = &dev->udev->dev; -+ memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template, -+ sizeof(struct i2c_adapter)); -+ dev->i2c_adapter.dev.parent = &dev->udev->dev; - -- i2c_set_adapdata(i2c_adap, dev); -+ i2c_set_adapdata(&dev->i2c_adapter, dev); - -- retval = i2c_add_adapter(i2c_adap); -+ retval = i2c_add_adapter(&dev->i2c_adapter); -+ if (retval) -+ goto error; - -- if (!retval) -- dev->i2c_adapter = i2c_adap; -- else -- kfree(i2c_adap); -+ i2c_new_device(&dev->i2c_adapter, &hdpvr_i2c_board_info); - - error: - return retval; - } -+ -+#endif -diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c -index c338f3f..26fd9bf 100644 ---- a/drivers/media/video/hdpvr/hdpvr-video.c -+++ b/drivers/media/video/hdpvr/hdpvr-video.c -@@ -1221,12 +1221,9 @@ static void hdpvr_device_release(struct video_device *vdev) - v4l2_device_unregister(&dev->v4l2_dev); - - /* deregister I2C adapter */ --#ifdef CONFIG_I2C -+#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE) - mutex_lock(&dev->i2c_mutex); -- if (dev->i2c_adapter) -- i2c_del_adapter(dev->i2c_adapter); -- kfree(dev->i2c_adapter); -- dev->i2c_adapter = NULL; -+ i2c_del_adapter(&dev->i2c_adapter); - mutex_unlock(&dev->i2c_mutex); - #endif /* CONFIG_I2C */ - -diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h -index b0f046d..2107055 100644 ---- a/drivers/media/video/hdpvr/hdpvr.h -+++ b/drivers/media/video/hdpvr/hdpvr.h -@@ -102,7 +102,7 @@ struct hdpvr_device { - struct work_struct worker; - - /* I2C adapter */ -- struct i2c_adapter *i2c_adapter; -+ struct i2c_adapter i2c_adapter; - /* I2C lock */ - struct mutex i2c_mutex; - -diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h -index 4bef5c5..4385341 100644 ---- a/include/linux/i2c-id.h -+++ b/include/linux/i2c-id.h -@@ -33,5 +33,6 @@ - - /* --- Bit algorithm adapters */ - #define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */ -+#define I2C_HW_B_HDPVR 0x010025 /* Hauppauge HD PVR */ - - #endif /* LINUX_I2C_ID_H */ diff --git a/kernel.spec b/kernel.spec index 1a358321e..d82cccbc0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -646,7 +646,6 @@ Patch399: acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch -Patch454: thinkpad-acpi-fix-backlight.patch Patch460: linux-2.6-serial-460800.patch @@ -702,7 +701,6 @@ Patch2910: linux-2.6-v4l-dvb-add-lgdt3304-support.patch Patch2912: linux-2.6-v4l-dvb-ir-core-update.patch #Patch2916: lirc-staging-2.6.36-fixes.patch -#Patch2917: hdpvr-ir-enable.patch Patch2918: flexcop-fix-xlate_proc_name-warning.patch @@ -1274,8 +1272,6 @@ ApplyPatch die-floppy-die.patch ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch -#ApplyPatch thinkpad-acpi-fix-backlight.patch - # Allow to use 480600 baud on 16C950 UARTs ApplyPatch linux-2.6-serial-460800.patch @@ -1340,8 +1336,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch # http://www.lirc.org/ #ApplyOptionalPatch lirc-staging-2.6.36-fixes.patch -# enable IR receiver on Hauppauge HD PVR (v4l-dvb merge pending) -#ApplyPatch hdpvr-ir-enable.patch # rhbz#664852 ApplyPatch flexcop-fix-xlate_proc_name-warning.patch @@ -1988,6 +1982,9 @@ fi %changelog * Fri Mar 25 2011 Chuck Ebbert - CVE-2011-1182: kernel signal spoofing issue +- Drop unused patches already applied upstream: + hdpvr-ir-enable.patch + thinkpad-acpi-fix-backlight.patch * Wed Mar 23 2011 Chuck Ebbert 2.6.38.1-6 - Linux 2.6.38.1 diff --git a/thinkpad-acpi-fix-backlight.patch b/thinkpad-acpi-fix-backlight.patch deleted file mode 100644 index 5ed2544fe..000000000 --- a/thinkpad-acpi-fix-backlight.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff -up linux-2.6.34.noarch/drivers/platform/x86/thinkpad_acpi.c.orig linux-2.6.34.noarch/drivers/platform/x86/thinkpad_acpi.c ---- linux-2.6.34.noarch/drivers/platform/x86/thinkpad_acpi.c.orig 2010-05-17 16:28:13.254200070 -0400 -+++ linux-2.6.34.noarch/drivers/platform/x86/thinkpad_acpi.c 2010-05-17 16:29:56.471200083 -0400 -@@ -3397,7 +3397,7 @@ static int __init hotkey_init(struct ibm - /* update bright_acpimode... */ - tpacpi_check_std_acpi_brightness_support(); - -- if (tp_features.bright_acpimode && acpi_video_backlight_support()) { -+ if (acpi_video_backlight_support()) { - printk(TPACPI_INFO - "This ThinkPad has standard ACPI backlight " - "brightness control, supported by the ACPI " -@@ -6189,26 +6189,24 @@ static int __init brightness_init(struct - * going to publish a backlight interface - */ - b = tpacpi_check_std_acpi_brightness_support(); -- if (b > 0) { - -- if (acpi_video_backlight_support()) { -- if (brightness_enable > 1) { -- printk(TPACPI_NOTICE -- "Standard ACPI backlight interface " -- "available, not loading native one.\n"); -- return 1; -- } else if (brightness_enable == 1) { -- printk(TPACPI_NOTICE -- "Backlight control force enabled, even if standard " -- "ACPI backlight interface is available\n"); -- } -- } else { -- if (brightness_enable > 1) { -- printk(TPACPI_NOTICE -- "Standard ACPI backlight interface not " -- "available, thinkpad_acpi native " -- "brightness control enabled\n"); -- } -+ if (acpi_video_backlight_support()) { -+ if (brightness_enable > 1) { -+ printk(TPACPI_NOTICE -+ "Standard ACPI backlight interface " -+ "available, not loading native one.\n"); -+ return 1; -+ } else if (brightness_enable == 1) { -+ printk(TPACPI_NOTICE -+ "Backlight control force enabled, even if standard " -+ "ACPI backlight interface is available\n"); -+ } -+ } else { -+ if (brightness_enable > 1) { -+ printk(TPACPI_NOTICE -+ "Standard ACPI backlight interface not " -+ "available, thinkpad_acpi native " -+ "brightness control enabled\n"); - } - } - From b0e7478b7153df1568ae9425d0850f95c3a67421 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 26 Mar 2011 08:15:11 -0400 Subject: [PATCH 10/99] Linux 2.6.38.2-rc1 --- kernel.spec | 13 ++++++++----- sources | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/kernel.spec b/kernel.spec index d82cccbc0..34fc5821c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -63,9 +63,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 1 +%define stable_update 2 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -1364,13 +1364,13 @@ ApplyPatch acpi_reboot.patch ApplyPatch dmar-disable-when-ricoh-multifunction.patch # rhbz#662344,600690 -ApplyPatch fs-call-security_d_instantiate-in-d_obtain_alias.patch +#ApplyPatch fs-call-security_d_instantiate-in-d_obtain_alias.patch # Fix possible memory corruption on Dell HW -ApplyPatch dcdbas-force-smi-to-happen-when-expected.patch +#ApplyPatch dcdbas-force-smi-to-happen-when-expected.patch # CVE-2011-1182 -ApplyPatch prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch +#ApplyPatch prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch # END OF PATCH APPLICATIONS @@ -1980,6 +1980,9 @@ fi # and build. %changelog +* Sat Mar 26 2011 Chuck Ebbert 2.6.38.2-7.rc1 +- Linux 2.6.38.2-rc1 + * Fri Mar 25 2011 Chuck Ebbert - CVE-2011-1182: kernel signal spoofing issue - Drop unused patches already applied upstream: diff --git a/sources b/sources index 69531329e..c01d99922 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 bd2be4d0465345e4e9355d6773f5f6fe patch-2.6.38.1.bz2 +71a62dab07960ac3a21304d99e7ac6da patch-2.6.38.2-rc1.bz2 From 1590df9db8861db30c721afe6299bb1d1221add2 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Mar 2011 18:59:28 -0400 Subject: [PATCH 11/99] Patch is now upstream, add its commit ID --- acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch | 2 ++ 1 file changed, 2 insertions(+) diff --git a/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch b/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch index b3256a2d3..ace336b47 100644 --- a/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch +++ b/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch @@ -7,6 +7,8 @@ Date: Wed, 23 Mar 2011 02:42:48 -0400 From: Kyle McMartin +Upstream commit 25be5821521640eb00b7eb219ffe59664510d073 + Commit da8aeb92 re-poked the battery on resume, but Linus reports that it broke his eee and partially reverted it in b23fffd7. Unfortunately this also results in my x201s giving crack values until the sysfs files From 073133a682770c1b879c184229788ef32e96a622 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Mar 2011 20:14:26 -0400 Subject: [PATCH 12/99] Fix more PCIe ASPM bugs - kworker task over 65% after resume (#683156) - ASPM powersave mode does not get enabled --- kernel.spec | 16 ++- ...-supported-features-not-enabled-ones.patch | 66 ----------- ...os-if-not-disabled-from-command-line.patch | 89 ++++++++++++++ ...igured-for-aspm-under-powersave-mode.patch | 112 ++++++++++++++++++ 4 files changed, 213 insertions(+), 70 deletions(-) delete mode 100644 pci-_osc-supported-field-should-contain-supported-features-not-enabled-ones.patch create mode 100644 pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch create mode 100644 pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch diff --git a/kernel.spec b/kernel.spec index 34fc5821c..b6ead48db 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 7 +%global baserelease 8 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -633,7 +633,6 @@ Patch204: linux-2.6-debug-always-inline-kzalloc.patch Patch380: linux-2.6-defaults-pci_no_msi.patch Patch381: linux-2.6-defaults-pci_use_crs.patch Patch383: linux-2.6-defaults-aspm.patch -Patch386: pci-_osc-supported-field-should-contain-supported-features-not-enabled-ones.patch Patch385: ima-allow-it-to-be-completely-disabled-and-default-off.patch @@ -728,6 +727,8 @@ Patch12200: acpi_reboot.patch Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12205: runtime_pm_fixups.patch +Patch12206: pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch +Patch12207: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1247,8 +1248,10 @@ ApplyPatch linux-2.6-defaults-pci_no_msi.patch ApplyPatch linux-2.6-defaults-pci_use_crs.patch # enable ASPM by default on hardware we expect to work ApplyPatch linux-2.6-defaults-aspm.patch -# rhbz#638912 -#ApplyPatch pci-_osc-supported-field-should-contain-supported-features-not-enabled-ones.patch +# rhbz #683156 +ApplyPatch pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch +# +ApplyPatch pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch #ApplyPatch ima-allow-it-to-be-completely-disabled-and-default-off.patch @@ -1980,6 +1983,11 @@ fi # and build. %changelog +* Sat Mar 26 2011 Chuck Ebbert +- Fix more PCIe ASPM bugs: + kworker task over 65% after resume (#683156) + ASPM powersave mode does not get enabled + * Sat Mar 26 2011 Chuck Ebbert 2.6.38.2-7.rc1 - Linux 2.6.38.2-rc1 diff --git a/pci-_osc-supported-field-should-contain-supported-features-not-enabled-ones.patch b/pci-_osc-supported-field-should-contain-supported-features-not-enabled-ones.patch deleted file mode 100644 index 0baffd639..000000000 --- a/pci-_osc-supported-field-should-contain-supported-features-not-enabled-ones.patch +++ /dev/null @@ -1,66 +0,0 @@ -commit 885c252ffb059dc493200bdb981bdd21cabe4442 -Author: Matthew Garrett -Date: Thu Dec 9 18:31:59 2010 -0500 - - PCI: _OSC "supported" field should contain supported features, not enabled ones - - From testing with Windows, the call to the PCI root _OSC method includes - the full set of features supported by the operating system even if the - hardware has already indicated that it doesn't support ASPM or MSI. - https://bugzilla.redhat.com/show_bug.cgi?id=638912 is a case where making - the _OSC call will incorrectly configure the chipset unless the supported - field has bits 1, 2 and 4 set. Rework the functionality to ensure that - we match this behaviour. - - Signed-off-by: Matthew Garrett - -diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c -index 96668ad..afb5d08 100644 ---- a/drivers/acpi/pci_root.c -+++ b/drivers/acpi/pci_root.c -@@ -450,7 +450,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) - struct acpi_pci_root *root; - acpi_handle handle; - struct acpi_device *child; -- u32 flags, base_flags; -+ u32 flags; - - root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); - if (!root) -@@ -498,10 +498,15 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) - device->driver_data = root; - - /* -- * All supported architectures that use ACPI have support for -- * PCI domains, so we indicate this in _OSC support capabilities. -+ * Indicate support for various _OSC capabilities. These match -+ * what the operating system supports, not what the hardware supports, -+ * so they shouldn't be conditional on functionality that's been -+ * blacklisted - */ -- flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; -+ flags = OSC_EXT_PCI_CONFIG_SUPPORT | OSC_ACTIVE_STATE_PWR_SUPPORT | -+ OSC_CLOCK_PWR_CAPABILITY_SUPPORT | -+ OSC_PCI_SEGMENT_GROUPS_SUPPORT | OSC_MSI_SUPPORT; -+ - acpi_pci_osc_support(root, flags); - - /* -@@ -555,17 +560,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) - list_for_each_entry(child, &device->children, node) - acpi_pci_bridge_scan(child); - -- /* Indicate support for various _OSC capabilities. */ -- if (pci_ext_cfg_avail(root->bus->self)) -- flags |= OSC_EXT_PCI_CONFIG_SUPPORT; -- if (pcie_aspm_enabled()) -- flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | -- OSC_CLOCK_PWR_CAPABILITY_SUPPORT; -- if (pci_msi_enabled()) -- flags |= OSC_MSI_SUPPORT; -- if (flags != base_flags) -- acpi_pci_osc_support(root, flags); -- - pci_acpi_add_bus_pm_notifier(device, root->bus); - if (device->wakeup.flags.run_wake) - device_set_run_wake(root->bus->bridge, true); diff --git a/pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch b/pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch new file mode 100644 index 000000000..8dccd1a09 --- /dev/null +++ b/pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch @@ -0,0 +1,89 @@ +From: Rafael J. Wysocki +Date: Sat, 5 Mar 2011 12:21:51 +0000 (+0100) +Subject: PCI/ACPI: Report ASPM support to BIOS if not disabled from command line +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8b8bae901ce23addbdcdb54fa1696fb2d049feb5 + +PCI/ACPI: Report ASPM support to BIOS if not disabled from command line + +We need to distinguish the situation in which ASPM support is +disabled from the command line or through .config from the situation +in which it is disabled, because the hardware or BIOS can't handle +it. In the former case we should not report ASPM support to the BIOS +through ACPI _OSC, but in the latter case we should do that. + +Introduce pcie_aspm_support_enabled() that can be used by +acpi_pci_root_add() to determine whether or not it should report ASPM +support to the BIOS through _OSC. + +Cc: stable@kernel.org +References: https://bugzilla.kernel.org/show_bug.cgi?id=29722 +References: https://bugzilla.kernel.org/show_bug.cgi?id=20232 +Reported-and-tested-by: Ortwin Glück +Reviewed-by: Kenji Kaneshige +Tested-by: Kenji Kaneshige +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Jesse Barnes +--- + +diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c +index 8524939..c7358dd 100644 +--- a/drivers/acpi/pci_root.c ++++ b/drivers/acpi/pci_root.c +@@ -564,7 +564,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) + /* Indicate support for various _OSC capabilities. */ + if (pci_ext_cfg_avail(root->bus->self)) + flags |= OSC_EXT_PCI_CONFIG_SUPPORT; +- if (pcie_aspm_enabled()) ++ if (pcie_aspm_support_enabled()) + flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | + OSC_CLOCK_PWR_CAPABILITY_SUPPORT; + if (pci_msi_enabled()) +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index 3188cd9..bbdb4fd 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -69,6 +69,7 @@ struct pcie_link_state { + }; + + static int aspm_disabled, aspm_force, aspm_clear_state; ++static bool aspm_support_enabled = true; + static DEFINE_MUTEX(aspm_lock); + static LIST_HEAD(link_list); + +@@ -896,6 +897,7 @@ static int __init pcie_aspm_disable(char *str) + { + if (!strcmp(str, "off")) { + aspm_disabled = 1; ++ aspm_support_enabled = false; + printk(KERN_INFO "PCIe ASPM is disabled\n"); + } else if (!strcmp(str, "force")) { + aspm_force = 1; +@@ -930,3 +932,8 @@ int pcie_aspm_enabled(void) + } + EXPORT_SYMBOL(pcie_aspm_enabled); + ++bool pcie_aspm_support_enabled(void) ++{ ++ return aspm_support_enabled; ++} ++EXPORT_SYMBOL(pcie_aspm_support_enabled); +diff --git a/include/linux/pci.h b/include/linux/pci.h +index 16c9f2e..96f70d7 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -1002,12 +1002,11 @@ extern bool pcie_ports_auto; + #endif + + #ifndef CONFIG_PCIEASPM +-static inline int pcie_aspm_enabled(void) +-{ +- return 0; +-} ++static inline int pcie_aspm_enabled(void) { return 0; } ++static inline bool pcie_aspm_support_enabled(void) { return false; } + #else + extern int pcie_aspm_enabled(void); ++extern bool pcie_aspm_support_enabled(void); + #endif + + #ifdef CONFIG_PCIEAER diff --git a/pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch b/pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch new file mode 100644 index 000000000..0c7f592ac --- /dev/null +++ b/pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch @@ -0,0 +1,112 @@ +From: Naga Chumbalkar +Date: Mon, 21 Mar 2011 03:29:08 +0000 (+0000) +Subject: PCI: PCIe links may not get configured for ASPM under POWERSAVE mode +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=1a680b7c325882188865f05b9a88d32f75f26495 + +PCI: PCIe links may not get configured for ASPM under POWERSAVE mode + +v3 -> v2: Moved ASPM enabling logic to pci_set_power_state() +v2 -> v1: Preserved the logic in pci_raw_set_power_state() + : Added ASPM enabling logic after scanning Root Bridge + : http://marc.info/?l=linux-pci&m=130046996216391&w=2 +v1 : http://marc.info/?l=linux-pci&m=130013164703283&w=2 + +The assumption made in commit 41cd766b065970ff6f6c89dd1cf55fa706c84a3d +(PCI: Don't enable aspm before drivers have had a chance to veto it) that +pci_enable_device() will result in re-configuring ASPM when aspm_policy is +POWERSAVE is no longer valid. This is due to commit +97c145f7c87453cec90e91238fba5fe2c1561b32 (PCI: read current power state +at enable time) which resets dev->current_state to D0. Due to this the +call to pcie_aspm_pm_state_change() is never made. Note the equality check +(below) that returns early: +./drivers/pci/pci.c: pci_raw_set_pci_power_state() +546 /* Check if we're already there */ +547 if (dev->current_state == state) +548 return 0; + +Therefore OSPM never configures the PCIe links for ASPM to turn them "on". + +Fix it by configuring ASPM from the pci_enable_device() code path. This +also allows a driver such as the e1000e networking driver a chance to +disable ASPM (L0s, L1), if need be, prior to enabling the device. A +driver may perform this action if the device is known to mis-behave +wrt ASPM. + +Signed-off-by: Naga Chumbalkar +Acked-by: Rafael J. Wysocki +Cc: Matthew Garrett +Signed-off-by: Jesse Barnes +--- + +diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c +index b714d78..2472e71 100644 +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -740,6 +740,12 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) + + if (!__pci_complete_power_transition(dev, state)) + error = 0; ++ /* ++ * When aspm_policy is "powersave" this call ensures ++ * that ASPM is configured. ++ */ ++ if (!error && dev->bus->self) ++ pcie_aspm_powersave_config_link(dev->bus->self); + + return error; + } +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index bbdb4fd..e61b82e 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -708,6 +708,28 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) + up_read(&pci_bus_sem); + } + ++void pcie_aspm_powersave_config_link(struct pci_dev *pdev) ++{ ++ struct pcie_link_state *link = pdev->link_state; ++ ++ if (aspm_disabled || !pci_is_pcie(pdev) || !link) ++ return; ++ ++ if (aspm_policy != POLICY_POWERSAVE) ++ return; ++ ++ if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && ++ (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) ++ return; ++ ++ down_read(&pci_bus_sem); ++ mutex_lock(&aspm_lock); ++ pcie_config_aspm_path(link); ++ pcie_set_clkpm(link, policy_to_clkpm_state(link)); ++ mutex_unlock(&aspm_lock); ++ up_read(&pci_bus_sem); ++} ++ + /* + * pci_disable_link_state - disable pci device's link state, so the link will + * never enter specific states +diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h +index ce68105..67cb3ae 100644 +--- a/include/linux/pci-aspm.h ++++ b/include/linux/pci-aspm.h +@@ -26,6 +26,7 @@ + extern void pcie_aspm_init_link_state(struct pci_dev *pdev); + extern void pcie_aspm_exit_link_state(struct pci_dev *pdev); + extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); ++extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev); + extern void pci_disable_link_state(struct pci_dev *pdev, int state); + extern void pcie_clear_aspm(void); + extern void pcie_no_aspm(void); +@@ -39,6 +40,9 @@ static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) + static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) + { + } ++static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) ++{ ++} + static inline void pci_disable_link_state(struct pci_dev *pdev, int state) + { + } From 3312da328f03296973671675077248b54a9e317b Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Mar 2011 20:23:02 -0400 Subject: [PATCH 13/99] Linux 2.6.38.2 --- kernel.spec | 5 +++-- sources | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index b6ead48db..8c9f1051d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -65,7 +65,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 2 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -1983,7 +1983,8 @@ fi # and build. %changelog -* Sat Mar 26 2011 Chuck Ebbert +* Sun Mar 27 2011 Chuck Ebbert 2.6.38.2-8 +- Linux 2.6.38.2 - Fix more PCIe ASPM bugs: kworker task over 65% after resume (#683156) ASPM powersave mode does not get enabled diff --git a/sources b/sources index c01d99922..e0d168044 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -bd2be4d0465345e4e9355d6773f5f6fe patch-2.6.38.1.bz2 -71a62dab07960ac3a21304d99e7ac6da patch-2.6.38.2-rc1.bz2 +599badab31c4920d4122133208c810d7 patch-2.6.38.2.bz2 From 75edc04edd2cef689d95e9e4131bad40b9a88ede Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Mar 2011 20:28:12 -0400 Subject: [PATCH 14/99] Drop patches merged in 2.6.38.2 --- ...as-force-smi-to-happen-when-expected.patch | 34 ---------- ...rity_d_instantiate-in-d_obtain_alias.patch | 64 ------------------- kernel.spec | 21 ++---- ...ueinfo-from-spoofing-the-signal-code.patch | 64 ------------------- 4 files changed, 4 insertions(+), 179 deletions(-) delete mode 100644 dcdbas-force-smi-to-happen-when-expected.patch delete mode 100644 fs-call-security_d_instantiate-in-d_obtain_alias.patch delete mode 100644 prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch diff --git a/dcdbas-force-smi-to-happen-when-expected.patch b/dcdbas-force-smi-to-happen-when-expected.patch deleted file mode 100644 index a7a2c8a36..000000000 --- a/dcdbas-force-smi-to-happen-when-expected.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Stuart Hayes -Date: Wed, 2 Mar 2011 12:42:05 +0000 (+0100) -Subject: dcdbas: force SMI to happen when expected -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=dd65c736d1b5312c80c88a64bf521db4959eded5 - -dcdbas: force SMI to happen when expected - -The dcdbas driver can do an I/O write to cause a SMI to occur. The SMI handler -looks at certain registers and memory locations, so the SMI needs to happen -immediately. On some systems I/O writes are posted, though, causing the SMI to -happen well after the "outb" occurred, which causes random failures. Following -the "outb" with an "inb" forces the write to go through even if it is posted. - -Signed-off-by: Stuart Hayes -Acked-by: Doug Warzecha -Signed-off-by: Jiri Kosina ---- - -diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c -index 69ad529..ea5ac2d 100644 ---- a/drivers/firmware/dcdbas.c -+++ b/drivers/firmware/dcdbas.c -@@ -268,8 +268,10 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd) - } - - /* generate SMI */ -+ /* inb to force posted write through and make SMI happen now */ - asm volatile ( -- "outb %b0,%w1" -+ "outb %b0,%w1\n" -+ "inb %w1" - : /* no output args */ - : "a" (smi_cmd->command_code), - "d" (smi_cmd->command_address), diff --git a/fs-call-security_d_instantiate-in-d_obtain_alias.patch b/fs-call-security_d_instantiate-in-d_obtain_alias.patch deleted file mode 100644 index 3bce47f5e..000000000 --- a/fs-call-security_d_instantiate-in-d_obtain_alias.patch +++ /dev/null @@ -1,64 +0,0 @@ -From linux-fsdevel-owner@vger.kernel.org Thu Nov 18 21:03:11 2010 -From: Josef Bacik -To: linux-fsdevel@vger.kernel.org, eparis@redhat.com, - linux-kernel@vger.kernel.org, sds@tycho.nsa.gov, - selinux@tycho.nsa.gov, bfields@fieldses.org -Subject: [PATCH] fs: call security_d_instantiate in d_obtain_alias V2 -Date: Thu, 18 Nov 2010 20:52:55 -0500 -Message-Id: <1290131575-2489-1-git-send-email-josef@redhat.com> -X-Mailing-List: linux-fsdevel@vger.kernel.org - -While trying to track down some NFS problems with BTRFS, I kept noticing I was -getting -EACCESS for no apparent reason. Eric Paris and printk() helped me -figure out that it was SELinux that was giving me grief, with the following -denial - -type=AVC msg=audit(1290013638.413:95): avc: denied { 0x800000 } for pid=1772 -comm="nfsd" name="" dev=sda1 ino=256 scontext=system_u:system_r:kernel_t:s0 -tcontext=system_u:object_r:unlabeled_t:s0 tclass=file - -Turns out this is because in d_obtain_alias if we can't find an alias we create -one and do all the normal instantiation stuff, but we don't do the -security_d_instantiate. - -Usually we are protected from getting a hashed dentry that hasn't yet run -security_d_instantiate() by the parent's i_mutex, but obviously this isn't an -option there, so in order to deal with the case that a second thread comes in -and finds our new dentry before we get to run security_d_instantiate(), we go -ahead and call it if we find a dentry already. Eric assures me that this is ok -as the code checks to see if the dentry has been initialized already so calling -security_d_instantiate() against the same dentry multiple times is ok. With -this patch I'm no longer getting errant -EACCESS values. - -Signed-off-by: Josef Bacik ---- -V1->V2: --added second security_d_instantiate() call - - fs/dcache.c | 3 +++ - 1 files changed, 3 insertions(+), 0 deletions(-) - -diff --git a/fs/dcache.c b/fs/dcache.c -index 5699d4c..85388fc 100644 ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -1577,9 +1577,13 @@ struct dentry *d_obtain_alias(struct inode *inode) - spin_unlock(&tmp->d_lock); - spin_unlock(&inode->i_lock); - -+ security_d_instantiate(tmp, inode); -+ - return tmp; - - out_iput: -+ if (res && !IS_ERR(res)) -+ security_d_instantiate(res, inode); - iput(inode); - return res; - } - --- -To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - diff --git a/kernel.spec b/kernel.spec index 8c9f1051d..c3f7a2c55 100644 --- a/kernel.spec +++ b/kernel.spec @@ -732,14 +732,6 @@ Patch12207: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode. Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch12421: fs-call-security_d_instantiate-in-d_obtain_alias.patch - -# Fix possible memory corruption on Dell HW -Patch12430: dcdbas-force-smi-to-happen-when-expected.patch - -# CVE-2011-1182 -Patch12431: prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1366,15 +1358,6 @@ ApplyPatch acpi_reboot.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -# rhbz#662344,600690 -#ApplyPatch fs-call-security_d_instantiate-in-d_obtain_alias.patch - -# Fix possible memory corruption on Dell HW -#ApplyPatch dcdbas-force-smi-to-happen-when-expected.patch - -# CVE-2011-1182 -#ApplyPatch prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch - # END OF PATCH APPLICATIONS %endif @@ -1985,6 +1968,10 @@ fi %changelog * Sun Mar 27 2011 Chuck Ebbert 2.6.38.2-8 - Linux 2.6.38.2 +- Drop patches merged in 2.6.38.2: + dcdbas-force-smi-to-happen-when-expected.patch + fs-call-security_d_instantiate-in-d_obtain_alias.patch + prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch - Fix more PCIe ASPM bugs: kworker task over 65% after resume (#683156) ASPM powersave mode does not get enabled diff --git a/prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch b/prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch deleted file mode 100644 index 747a0e330..000000000 --- a/prevent-rt_sigqueueinfo-and-rt_tgsigqueueinfo-from-spoofing-the-signal-code.patch +++ /dev/null @@ -1,64 +0,0 @@ -From: Julien Tinnes -Date: Fri, 18 Mar 2011 22:05:21 +0000 (-0700) -Subject: Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal code -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=da48524eb20662618854bb3df2db01fc65f3070c - -Prevent rt_sigqueueinfo and rt_tgsigqueueinfo from spoofing the signal code - -Userland should be able to trust the pid and uid of the sender of a -signal if the si_code is SI_TKILL. - -Unfortunately, the kernel has historically allowed sigqueueinfo() to -send any si_code at all (as long as it was negative - to distinguish it -from kernel-generated signals like SIGILL etc), so it could spoof a -SI_TKILL with incorrect siginfo values. - -Happily, it looks like glibc has always set si_code to the appropriate -SI_QUEUE, so there are probably no actual user code that ever uses -anything but the appropriate SI_QUEUE flag. - -So just tighten the check for si_code (we used to allow any negative -value), and add a (one-time) warning in case there are binaries out -there that might depend on using other si_code values. - -Signed-off-by: Julien Tinnes -Acked-by: Oleg Nesterov -Signed-off-by: Linus Torvalds ---- - -diff --git a/kernel/signal.c b/kernel/signal.c -index 4e3cff1..3175186 100644 ---- a/kernel/signal.c -+++ b/kernel/signal.c -@@ -2421,9 +2421,13 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig, - return -EFAULT; - - /* Not even root can pretend to send signals from the kernel. -- Nor can they impersonate a kill(), which adds source info. */ -- if (info.si_code >= 0) -+ * Nor can they impersonate a kill()/tgkill(), which adds source info. -+ */ -+ if (info.si_code != SI_QUEUE) { -+ /* We used to allow any < 0 si_code */ -+ WARN_ON_ONCE(info.si_code < 0); - return -EPERM; -+ } - info.si_signo = sig; - - /* POSIX.1b doesn't mention process groups. */ -@@ -2437,9 +2441,13 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) - return -EINVAL; - - /* Not even root can pretend to send signals from the kernel. -- Nor can they impersonate a kill(), which adds source info. */ -- if (info->si_code >= 0) -+ * Nor can they impersonate a kill()/tgkill(), which adds source info. -+ */ -+ if (info->si_code != SI_QUEUE) { -+ /* We used to allow any < 0 si_code */ -+ WARN_ON_ONCE(info->si_code < 0); - return -EPERM; -+ } - info->si_signo = sig; - - return do_send_specific(tgid, pid, sig, info); From 7a46f6afe6e637542159a31edbeab3f17c20f6f6 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 27 Mar 2011 22:58:06 -0400 Subject: [PATCH 15/99] Drop obsolete prevent-runtime-conntrack-changes.patch --- kernel.spec | 2 - prevent-runtime-conntrack-changes.patch | 74 ------------------------- 2 files changed, 76 deletions(-) delete mode 100644 prevent-runtime-conntrack-changes.patch diff --git a/kernel.spec b/kernel.spec index c3f7a2c55..2ababf813 100644 --- a/kernel.spec +++ b/kernel.spec @@ -715,8 +715,6 @@ Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch -Patch12017: prevent-runtime-conntrack-changes.patch - Patch12018: neuter_intel_microcode_load.patch Patch12101: apple_backlight.patch diff --git a/prevent-runtime-conntrack-changes.patch b/prevent-runtime-conntrack-changes.patch deleted file mode 100644 index 59d62f3de..000000000 --- a/prevent-runtime-conntrack-changes.patch +++ /dev/null @@ -1,74 +0,0 @@ -Jon Masters correctly points out that conntrack hash sizes -(nf_conntrack_htable_size) are global (not per-netns) and -modifiable at runtime via /sys/module/nf_conntrack/hashsize . - -Steps to reproduce: - clone(CLONE_NEWNET) - [grow /sys/module/nf_conntrack/hashsize] - exit() - -At netns exit we are going to scan random memory for conntracks to be killed. - -Apparently there is a code which deals with hashtable resize for -init_net (and it was there befode netns conntrack code), so prohibit -hashsize modification if there is more than one netns exists. - -To change hashtable sizes, you need to reload module. - -Expectation hashtable size was simply glued to a variable with no code -to rehash expectations, so it was a bug to allow writing to it. -Make "expect_hashsize" readonly. - -This is temporarily until we figure out what to do. - -Signed-off-by: Alexey Dobriyan -Cc: stable@kernel.org ---- - - net/netfilter/nf_conntrack_core.c | 15 +++++++++++++++ - net/netfilter/nf_conntrack_expect.c | 2 +- - 2 files changed, 16 insertions(+), 1 deletion(-) - ---- a/net/netfilter/nf_conntrack_core.c -+++ b/net/netfilter/nf_conntrack_core.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1198,6 +1199,20 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) - if (!nf_conntrack_htable_size) - return param_set_uint(val, kp); - -+ { -+ struct net *net; -+ unsigned int nr; -+ -+ nr = 0; -+ rtnl_lock(); -+ for_each_net(net) -+ nr++; -+ rtnl_unlock(); -+ /* init_net always exists */ -+ if (nr != 1) -+ return -EINVAL; -+ } -+ - hashsize = simple_strtoul(val, NULL, 0); - if (!hashsize) - return -EINVAL; ---- a/net/netfilter/nf_conntrack_expect.c -+++ b/net/netfilter/nf_conntrack_expect.c -@@ -569,7 +569,7 @@ static void exp_proc_remove(struct net *net) - #endif /* CONFIG_PROC_FS */ - } - --module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600); -+module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400); - - int nf_conntrack_expect_init(struct net *net) - { - From 1d3db7f8fbb135e9cd6627da77f84bcfc6ef2a81 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 29 Mar 2011 19:17:20 -0400 Subject: [PATCH 16/99] printk: do not mangle valid userspace syslog prefixes printk: do not mangle valid userspace syslog prefixes with /dev/kmsg (#691888) The patch is upstream in 2.6.39, and Lennart tells me the patch has been backported for the next Suse release as well. --- kernel.spec | 11 + ...ngle-valid-userspace-syslog-prefixes.patch | 214 ++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 printk-do-not-mangle-valid-userspace-syslog-prefixes.patch diff --git a/kernel.spec b/kernel.spec index 2ababf813..045971ec0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -730,6 +730,8 @@ Patch12207: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode. Patch12303: dmar-disable-when-ricoh-multifunction.patch +Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1356,6 +1358,9 @@ ApplyPatch acpi_reboot.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch +# rhbz#691888 +ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch + # END OF PATCH APPLICATIONS %endif @@ -1964,6 +1969,12 @@ fi # and build. %changelog +* Tue Mar 29 2011 Kyle McMartin +- printk: do not mangle valid userspace syslog prefixes with + /dev/kmsg (#691888) + - The patch is upstream in 2.6.39, and Lennart tells me the patch has been + backported for the next Suse release as well. + * Sun Mar 27 2011 Chuck Ebbert 2.6.38.2-8 - Linux 2.6.38.2 - Drop patches merged in 2.6.38.2: diff --git a/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch b/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch new file mode 100644 index 000000000..73885ae57 --- /dev/null +++ b/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch @@ -0,0 +1,214 @@ +From: Kay Sievers +Date: Sun, 13 Mar 2011 02:19:51 +0000 (+0100) +Subject: printk: do not mangle valid userspace syslog prefixes +X-Git-Tag: v2.6.39-rc1~471^2 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9d90c8d9cde929cbc575098e825d7c29d9f45054 + +printk: do not mangle valid userspace syslog prefixes + +printk: do not mangle valid userspace syslog prefixes with /dev/kmsg + +Log messages passed to the kernel log by using /dev/kmsg or /dev/ttyprintk +might contain a syslog prefix including the syslog facility value. + +This makes printk to recognize these headers properly, extract the real log +level from it to use, and add the prefix as a proper prefix to the +log buffer, instead of wrongly printing it as the log message text. + +Before: + $ echo '<14>text' > /dev/kmsg + $ dmesg -r + <4>[135159.594810] <14>text + +After: + $ echo '<14>text' > /dev/kmsg + $ dmesg -r + <14>[ 50.750654] text + +Cc: Lennart Poettering +Signed-off-by: Kay Sievers +Signed-off-by: Greg Kroah-Hartman +--- + +diff --git a/kernel/printk.c b/kernel/printk.c +index 2ddbdc7..5e3d042 100644 +--- a/kernel/printk.c ++++ b/kernel/printk.c +@@ -499,6 +499,71 @@ static void _call_console_drivers(unsigned start, + } + + /* ++ * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the ++ * lower 3 bit are the log level, the rest are the log facility. In case ++ * userspace passes usual userspace syslog messages to /dev/kmsg or ++ * /dev/ttyprintk, the log prefix might contain the facility. Printk needs ++ * to extract the correct log level for in-kernel processing, and not mangle ++ * the original value. ++ * ++ * If a prefix is found, the length of the prefix is returned. If 'level' is ++ * passed, it will be filled in with the log level without a possible facility ++ * value. If 'special' is passed, the special printk prefix chars are accepted ++ * and returned. If no valid header is found, 0 is returned and the passed ++ * variables are not touched. ++ */ ++static size_t log_prefix(const char *p, unsigned int *level, char *special) ++{ ++ unsigned int lev = 0; ++ char sp = '\0'; ++ size_t len; ++ ++ if (p[0] != '<' || !p[1]) ++ return 0; ++ if (p[2] == '>') { ++ /* usual single digit level number or special char */ ++ switch (p[1]) { ++ case '0' ... '7': ++ lev = p[1] - '0'; ++ break; ++ case 'c': /* KERN_CONT */ ++ case 'd': /* KERN_DEFAULT */ ++ sp = p[1]; ++ break; ++ default: ++ return 0; ++ } ++ len = 3; ++ } else { ++ /* multi digit including the level and facility number */ ++ char *endp = NULL; ++ ++ if (p[1] < '0' && p[1] > '9') ++ return 0; ++ ++ lev = (simple_strtoul(&p[1], &endp, 10) & 7); ++ if (endp == NULL || endp[0] != '>') ++ return 0; ++ len = (endp + 1) - p; ++ } ++ ++ /* do not accept special char if not asked for */ ++ if (sp && !special) ++ return 0; ++ ++ if (special) { ++ *special = sp; ++ /* return special char, do not touch level */ ++ if (sp) ++ return len; ++ } ++ ++ if (level) ++ *level = lev; ++ return len; ++} ++ ++/* + * Call the console drivers, asking them to write out + * log_buf[start] to log_buf[end - 1]. + * The console_lock must be held. +@@ -513,13 +578,9 @@ static void call_console_drivers(unsigned start, unsigned end) + cur_index = start; + start_print = start; + while (cur_index != end) { +- if (msg_level < 0 && ((end - cur_index) > 2) && +- LOG_BUF(cur_index + 0) == '<' && +- LOG_BUF(cur_index + 1) >= '0' && +- LOG_BUF(cur_index + 1) <= '7' && +- LOG_BUF(cur_index + 2) == '>') { +- msg_level = LOG_BUF(cur_index + 1) - '0'; +- cur_index += 3; ++ if (msg_level < 0 && ((end - cur_index) > 2)) { ++ /* strip log prefix */ ++ cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL); + start_print = cur_index; + } + while (cur_index != end) { +@@ -717,6 +778,8 @@ asmlinkage int vprintk(const char *fmt, va_list args) + unsigned long flags; + int this_cpu; + char *p; ++ size_t plen; ++ char special; + + boot_delay_msec(); + printk_delay(); +@@ -757,45 +820,52 @@ asmlinkage int vprintk(const char *fmt, va_list args) + printed_len += vscnprintf(printk_buf + printed_len, + sizeof(printk_buf) - printed_len, fmt, args); + +- + p = printk_buf; + +- /* Do we have a loglevel in the string? */ +- if (p[0] == '<') { +- unsigned char c = p[1]; +- if (c && p[2] == '>') { +- switch (c) { +- case '0' ... '7': /* loglevel */ +- current_log_level = c - '0'; +- /* Fallthrough - make sure we're on a new line */ +- case 'd': /* KERN_DEFAULT */ +- if (!new_text_line) { +- emit_log_char('\n'); +- new_text_line = 1; +- } +- /* Fallthrough - skip the loglevel */ +- case 'c': /* KERN_CONT */ +- p += 3; +- break; ++ /* Read log level and handle special printk prefix */ ++ plen = log_prefix(p, ¤t_log_level, &special); ++ if (plen) { ++ p += plen; ++ ++ switch (special) { ++ case 'c': /* Strip KERN_CONT, continue line */ ++ plen = 0; ++ break; ++ case 'd': /* Strip KERN_DEFAULT, start new line */ ++ plen = 0; ++ default: ++ if (!new_text_line) { ++ emit_log_char('\n'); ++ new_text_line = 1; + } + } + } + + /* +- * Copy the output into log_buf. If the caller didn't provide +- * appropriate log level tags, we insert them here ++ * Copy the output into log_buf. If the caller didn't provide ++ * the appropriate log prefix, we insert them here + */ +- for ( ; *p; p++) { ++ for (; *p; p++) { + if (new_text_line) { +- /* Always output the token */ +- emit_log_char('<'); +- emit_log_char(current_log_level + '0'); +- emit_log_char('>'); +- printed_len += 3; + new_text_line = 0; + ++ if (plen) { ++ /* Copy original log prefix */ ++ int i; ++ ++ for (i = 0; i < plen; i++) ++ emit_log_char(printk_buf[i]); ++ printed_len += plen; ++ } else { ++ /* Add log prefix */ ++ emit_log_char('<'); ++ emit_log_char(current_log_level + '0'); ++ emit_log_char('>'); ++ printed_len += 3; ++ } ++ + if (printk_time) { +- /* Follow the token with the time */ ++ /* Add the current time stamp */ + char tbuf[50], *tp; + unsigned tlen; + unsigned long long t; From 1862e7dee1c4a99273b7cf7b06b171f2537ae337 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 29 Mar 2011 19:47:10 -0400 Subject: [PATCH 17/99] disable qla4xxx on ppc32 --- config-powerpc32-generic | 3 +++ kernel.spec | 1 + 2 files changed, 4 insertions(+) diff --git a/config-powerpc32-generic b/config-powerpc32-generic index d2304955f..b18a845c1 100644 --- a/config-powerpc32-generic +++ b/config-powerpc32-generic @@ -182,3 +182,6 @@ CONFIG_PERF_EVENTS=y CONFIG_EVENT_PROFILE=y CONFIG_KVM_BOOK3S_32=m + +### needs non-existant readq/writeq +# CONFIG_SCSI_QLA_ISCSI is not set diff --git a/kernel.spec b/kernel.spec index 045971ec0..275491dc3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1974,6 +1974,7 @@ fi /dev/kmsg (#691888) - The patch is upstream in 2.6.39, and Lennart tells me the patch has been backported for the next Suse release as well. +- Disable qla4xxx (CONFIG_SCSI_QLA_ISCSI) driver on powerpc32 (#686199) * Sun Mar 27 2011 Chuck Ebbert 2.6.38.2-8 - Linux 2.6.38.2 From 755fd341e761cf3ff402950f34b0cb33afe4f083 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 29 Mar 2011 21:18:02 -0400 Subject: [PATCH 18/99] disable tpm/ima on ppc --- config-powerpc-generic | 3 +++ config-powerpc32-generic | 1 - kernel.spec | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/config-powerpc-generic b/config-powerpc-generic index 9cd30a459..3c8d8f058 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -338,3 +338,6 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m CONFIG_MPC512X_DMA=m CONFIG_KVM_GUEST=y + +# CONFIG_IMA is not set +# CONFIG_TCG_TPM is not set diff --git a/config-powerpc32-generic b/config-powerpc32-generic index b18a845c1..daa06ab57 100644 --- a/config-powerpc32-generic +++ b/config-powerpc32-generic @@ -137,7 +137,6 @@ CONFIG_VIRTUALIZATION=y # CONFIG_MEMSTICK is not set # CONFIG_IPMI_HANDLER is not set -# CONFIG_TCG_TPM is not set # PPC gets sad with debug alloc (bz 448598) # CONFIG_DEBUG_PAGEALLOC is not set diff --git a/kernel.spec b/kernel.spec index 275491dc3..98cbfe9f0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1969,6 +1969,9 @@ fi # and build. %changelog +* Tue Mar 29 2011 Kyle McMartin +- Disable CONFIG_IMA, CONFIG_TCG_TPM on powerpc (#689468) + * Tue Mar 29 2011 Kyle McMartin - printk: do not mangle valid userspace syslog prefixes with /dev/kmsg (#691888) From 86c0bad77a859f50bfa008160c278e748fd2c9eb Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 30 Mar 2011 12:13:45 -0400 Subject: [PATCH 19/99] drop scsi sd printks about caching from error to notice --- kernel.spec | 11 +++++++- ...-caching-printk-from-error-to-notice.patch | 27 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 scsi-sd-downgrade-caching-printk-from-error-to-notice.patch diff --git a/kernel.spec b/kernel.spec index 98cbfe9f0..5ec21a5c2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 8 +%global baserelease 9 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -731,6 +731,7 @@ Patch12207: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode. Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch +Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch %endif @@ -1361,6 +1362,8 @@ ApplyPatch dmar-disable-when-ricoh-multifunction.patch # rhbz#691888 ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch +ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch + # END OF PATCH APPLICATIONS %endif @@ -1969,6 +1972,12 @@ fi # and build. %changelog +* Wed Mar 29 2011 Kyle McMartin 2.6.38.2-9 +- Downgrade SCSI sd printk's about disk caching from KERN_ERR to KERN_NOTICE + so they don't show up in our pretty quiet boot. Ray noticed them when + booting from a USB stick which doesn't have a cache page returned in the + sense buffer. + * Tue Mar 29 2011 Kyle McMartin - Disable CONFIG_IMA, CONFIG_TCG_TPM on powerpc (#689468) diff --git a/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch b/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch new file mode 100644 index 000000000..47ebbaddb --- /dev/null +++ b/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch @@ -0,0 +1,27 @@ +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index e567302..261638a 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1988,11 +1988,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) + } + + if (modepage == 0x3F) { +- sd_printk(KERN_ERR, sdkp, "No Caching mode page " ++ sd_printk(KERN_NOTICE, sdkp, "No Caching mode page " + "present\n"); + goto defaults; + } else if ((buffer[offset] & 0x3f) != modepage) { +- sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); ++ sd_printk(KERN_NOTICE, sdkp, "Got wrong page\n"); + goto defaults; + } + Page_found: +@@ -2033,7 +2033,7 @@ bad_sense: + sd_printk(KERN_ERR, sdkp, "Asking for cache data failed\n"); + + defaults: +- sd_printk(KERN_ERR, sdkp, "Assuming drive cache: write through\n"); ++ sd_printk(KERN_NOTICE, sdkp, "Assuming drive cache: write through\n"); + sdkp->WCE = 0; + sdkp->RCD = 0; + sdkp->DPOFUA = 0; From abe10d7eb7436952b118fb058ab048b06497af87 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 31 Mar 2011 12:53:14 +1000 Subject: [PATCH 20/99] nouveau: stability fixes, zcomp, page flipping --- drm-nouveau-updates.patch | 4219 +++++++++++++++++++++++++++++++++++-- kernel.spec | 8 +- 2 files changed, 4066 insertions(+), 161 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 90a716dba..9c032f4df 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,36 +1,5 @@ - drivers/gpu/drm/nouveau/nouveau_bios.c | 78 +++++-- - drivers/gpu/drm/nouveau/nouveau_bo.c | 6 +- - drivers/gpu/drm/nouveau/nouveau_channel.c | 2 +- - drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- - drivers/gpu/drm/nouveau/nouveau_dp.c | 2 - - drivers/gpu/drm/nouveau/nouveau_drv.h | 15 +- - drivers/gpu/drm/nouveau/nouveau_fence.c | 205 +++++++++++------ - drivers/gpu/drm/nouveau/nouveau_mem.c | 50 +++- - drivers/gpu/drm/nouveau/nouveau_object.c | 22 ++- - drivers/gpu/drm/nouveau/nouveau_perf.c | 2 +- - drivers/gpu/drm/nouveau/nouveau_sgdma.c | 341 +++++++++++++++++++++++++---- - drivers/gpu/drm/nouveau/nouveau_state.c | 10 +- - drivers/gpu/drm/nouveau/nouveau_temp.c | 4 +- - drivers/gpu/drm/nouveau/nouveau_util.c | 23 ++- - drivers/gpu/drm/nouveau/nouveau_util.h | 4 + - drivers/gpu/drm/nouveau/nouveau_vm.c | 13 +- - drivers/gpu/drm/nouveau/nv04_dfp.c | 13 +- - drivers/gpu/drm/nouveau/nv04_fifo.c | 19 ++- - drivers/gpu/drm/nouveau/nv40_fb.c | 59 +++++- - drivers/gpu/drm/nouveau/nv50_display.c | 7 +- - drivers/gpu/drm/nouveau/nv50_evo.c | 1 + - drivers/gpu/drm/nouveau/nv50_fb.c | 150 ++++++++++++- - drivers/gpu/drm/nouveau/nv50_fifo.c | 3 +- - drivers/gpu/drm/nouveau/nv50_gpio.c | 13 +- - drivers/gpu/drm/nouveau/nv50_graph.c | 142 +++++++----- - drivers/gpu/drm/nouveau/nv50_vm.c | 1 - - drivers/gpu/drm/nouveau/nv84_crypt.c | 2 +- - drivers/gpu/drm/nouveau/nvc0_fifo.c | 15 +- - drivers/gpu/drm/nouveau/nvc0_graph.c | 2 - - 29 files changed, 912 insertions(+), 294 deletions(-) - diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c -index 6bdab89..1bb1261 100644 +index 6bdab89..90aef64 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -269,7 +269,7 @@ struct init_tbl_entry { @@ -42,6 +11,33 @@ index 6bdab89..1bb1261 100644 #define MACRO_INDEX_SIZE 2 #define MACRO_SIZE 8 +@@ -282,7 +282,7 @@ static void still_alive(void) + { + #if 0 + sync(); +- msleep(2); ++ mdelay(2); + #endif + } + +@@ -1904,7 +1904,7 @@ init_condition_time(struct nvbios *bios, uint16_t offset, + BIOSLOG(bios, "0x%04X: " + "Condition not met, sleeping for 20ms\n", + offset); +- msleep(20); ++ mdelay(20); + } + } + +@@ -1938,7 +1938,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n", + offset, time); + +- msleep(time); ++ mdelay(time); + + return 3; + } @@ -2011,6 +2011,27 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) } @@ -70,6 +66,15 @@ index 6bdab89..1bb1261 100644 init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* +@@ -2962,7 +2983,7 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) + if (time < 1000) + udelay(time); + else +- msleep((time + 900) / 1000); ++ mdelay((time + 900) / 1000); + + return 3; + } @@ -3659,6 +3680,7 @@ static struct init_tbl_entry itbl_entry[] = { { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ @@ -88,6 +93,15 @@ index 6bdab89..1bb1261 100644 { /* * Parses all commands in an init table. +@@ -3856,7 +3877,7 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr + + if (script == LVDS_PANEL_OFF) { + /* off-on delay in ms */ +- msleep(ROM16(bios->data[bios->fp.xlated_entry + 7])); ++ mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7])); + } + #ifdef __powerpc__ + /* Powerbook specific quirks */ @@ -5950,6 +5971,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) } } @@ -160,11 +174,124 @@ index 6bdab89..1bb1261 100644 return true; } +@@ -6702,11 +6740,11 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, + struct nvbios *bios = &dev_priv->vbios; + struct init_exec iexec = { true, false }; + +- mutex_lock(&bios->lock); ++ spin_lock_bh(&bios->lock); + bios->display.output = dcbent; + parse_init_table(bios, table, &iexec); + bios->display.output = NULL; +- mutex_unlock(&bios->lock); ++ spin_unlock_bh(&bios->lock); + } + + static bool NVInitVBIOS(struct drm_device *dev) +@@ -6715,7 +6753,7 @@ static bool NVInitVBIOS(struct drm_device *dev) + struct nvbios *bios = &dev_priv->vbios; + + memset(bios, 0, sizeof(struct nvbios)); +- mutex_init(&bios->lock); ++ spin_lock_init(&bios->lock); + bios->dev = dev; + + if (!NVShadowVBIOS(dev, bios->data)) +diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h +index 50a648e..8a54fa7 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bios.h ++++ b/drivers/gpu/drm/nouveau/nouveau_bios.h +@@ -251,7 +251,7 @@ struct nvbios { + uint8_t digital_min_front_porch; + bool fp_no_ddc; + +- struct mutex lock; ++ spinlock_t lock; + + uint8_t data[NV_PROM_SIZE]; + unsigned int length; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c -index a521840..53a8000 100644 +index a521840..2ad49cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c -@@ -385,7 +385,8 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) +@@ -57,8 +57,8 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) + } + + static void +-nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, +- int *page_shift) ++nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, ++ int *align, int *size, int *page_shift) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); + +@@ -83,7 +83,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, + } + } else { + if (likely(dev_priv->chan_vm)) { +- if (*size > 256 * 1024) ++ if (!(flags & TTM_PL_FLAG_TT) && *size > 256 * 1024) + *page_shift = dev_priv->chan_vm->lpg_shift; + else + *page_shift = dev_priv->chan_vm->spg_shift; +@@ -101,8 +101,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, + int + nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, + int size, int align, uint32_t flags, uint32_t tile_mode, +- uint32_t tile_flags, bool no_vm, bool mappable, +- struct nouveau_bo **pnvbo) ++ uint32_t tile_flags, struct nouveau_bo **pnvbo) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *nvbo; +@@ -113,16 +112,14 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, + return -ENOMEM; + INIT_LIST_HEAD(&nvbo->head); + INIT_LIST_HEAD(&nvbo->entry); +- nvbo->mappable = mappable; +- nvbo->no_vm = no_vm; + nvbo->tile_mode = tile_mode; + nvbo->tile_flags = tile_flags; + nvbo->bo.bdev = &dev_priv->ttm.bdev; + +- nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift); ++ nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift); + align >>= PAGE_SHIFT; + +- if (!nvbo->no_vm && dev_priv->chan_vm) { ++ if (dev_priv->chan_vm) { + ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, + NV_MEM_ACCESS_RW, &nvbo->vma); + if (ret) { +@@ -144,11 +141,8 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, + } + nvbo->channel = NULL; + +- if (nvbo->vma.node) { +- if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) +- nvbo->bo.offset = nvbo->vma.offset; +- } +- ++ if (nvbo->vma.node) ++ nvbo->bo.offset = nvbo->vma.offset; + *pnvbo = nvbo; + return 0; + } +@@ -318,11 +312,8 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible, + if (ret) + return ret; + +- if (nvbo->vma.node) { +- if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) +- nvbo->bo.offset = nvbo->vma.offset; +- } +- ++ if (nvbo->vma.node) ++ nvbo->bo.offset = nvbo->vma.offset; + return 0; + } + +@@ -385,7 +376,8 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) case NOUVEAU_GART_AGP: return ttm_agp_backend_init(bdev, dev->agp->bridge); #endif @@ -174,7 +301,19 @@ index a521840..53a8000 100644 return nouveau_sgdma_init_ttm(dev); default: NV_ERROR(dev, "Unknown GART type %d\n", -@@ -439,7 +440,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, +@@ -431,7 +423,10 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, + man->default_caching = TTM_PL_FLAG_WC; + break; + case TTM_PL_TT: +- man->func = &ttm_bo_manager_func; ++ if (dev_priv->card_type >= NV_50) ++ man->func = &nouveau_gart_manager; ++ else ++ man->func = &ttm_bo_manager_func; + switch (dev_priv->gart_info.type) { + case NOUVEAU_GART_AGP: + man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; +@@ -439,7 +434,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; break; @@ -184,8 +323,378 @@ index a521840..53a8000 100644 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; man->available_caching = TTM_PL_MASK_CACHING; +@@ -501,45 +497,22 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, + return ret; + } + +-static inline uint32_t +-nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, +- struct nouveau_channel *chan, struct ttm_mem_reg *mem) +-{ +- struct nouveau_bo *nvbo = nouveau_bo(bo); +- +- if (nvbo->no_vm) { +- if (mem->mem_type == TTM_PL_TT) +- return NvDmaGART; +- return NvDmaVRAM; +- } +- +- if (mem->mem_type == TTM_PL_TT) +- return chan->gart_handle; +- return chan->vram_handle; +-} +- + static int + nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) + { +- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ struct nouveau_mem *old_node = old_mem->mm_node; ++ struct nouveau_mem *new_node = new_mem->mm_node; + struct nouveau_bo *nvbo = nouveau_bo(bo); +- u64 src_offset = old_mem->start << PAGE_SHIFT; +- u64 dst_offset = new_mem->start << PAGE_SHIFT; + u32 page_count = new_mem->num_pages; ++ u64 src_offset, dst_offset; + int ret; + +- if (!nvbo->no_vm) { +- if (old_mem->mem_type == TTM_PL_VRAM) +- src_offset = nvbo->vma.offset; +- else +- src_offset += dev_priv->gart_info.aper_base; +- +- if (new_mem->mem_type == TTM_PL_VRAM) +- dst_offset = nvbo->vma.offset; +- else +- dst_offset += dev_priv->gart_info.aper_base; +- } ++ src_offset = old_node->tmp_vma.offset; ++ if (new_node->tmp_vma.node) ++ dst_offset = new_node->tmp_vma.offset; ++ else ++ dst_offset = nvbo->vma.offset; + + page_count = new_mem->num_pages; + while (page_count) { +@@ -574,33 +547,18 @@ static int + nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) + { +- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ struct nouveau_mem *old_node = old_mem->mm_node; ++ struct nouveau_mem *new_node = new_mem->mm_node; + struct nouveau_bo *nvbo = nouveau_bo(bo); + u64 length = (new_mem->num_pages << PAGE_SHIFT); + u64 src_offset, dst_offset; + int ret; + +- src_offset = old_mem->start << PAGE_SHIFT; +- dst_offset = new_mem->start << PAGE_SHIFT; +- if (!nvbo->no_vm) { +- if (old_mem->mem_type == TTM_PL_VRAM) +- src_offset = nvbo->vma.offset; +- else +- src_offset += dev_priv->gart_info.aper_base; +- +- if (new_mem->mem_type == TTM_PL_VRAM) +- dst_offset = nvbo->vma.offset; +- else +- dst_offset += dev_priv->gart_info.aper_base; +- } +- +- ret = RING_SPACE(chan, 3); +- if (ret) +- return ret; +- +- BEGIN_RING(chan, NvSubM2MF, 0x0184, 2); +- OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); +- OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); ++ src_offset = old_node->tmp_vma.offset; ++ if (new_node->tmp_vma.node) ++ dst_offset = new_node->tmp_vma.offset; ++ else ++ dst_offset = nvbo->vma.offset; + + while (length) { + u32 amount, stride, height; +@@ -681,6 +639,15 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + return 0; + } + ++static inline uint32_t ++nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, ++ struct nouveau_channel *chan, struct ttm_mem_reg *mem) ++{ ++ if (mem->mem_type == TTM_PL_TT) ++ return chan->gart_handle; ++ return chan->vram_handle; ++} ++ + static int + nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, + struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) +@@ -734,15 +701,43 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); ++ struct ttm_mem_reg *old_mem = &bo->mem; + struct nouveau_channel *chan; + int ret; + + chan = nvbo->channel; +- if (!chan || nvbo->no_vm) { ++ if (!chan) { + chan = dev_priv->channel; + mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); + } + ++ /* create temporary vma for old memory, this will get cleaned ++ * up after ttm destroys the ttm_mem_reg ++ */ ++ if (dev_priv->card_type >= NV_50) { ++ struct nouveau_mem *node = old_mem->mm_node; ++ if (!node->tmp_vma.node) { ++ u32 page_shift = nvbo->vma.node->type; ++ if (old_mem->mem_type == TTM_PL_TT) ++ page_shift = nvbo->vma.vm->spg_shift; ++ ++ ret = nouveau_vm_get(chan->vm, ++ old_mem->num_pages << PAGE_SHIFT, ++ page_shift, NV_MEM_ACCESS_RO, ++ &node->tmp_vma); ++ if (ret) ++ goto out; ++ } ++ ++ if (old_mem->mem_type == TTM_PL_VRAM) ++ nouveau_vm_map(&node->tmp_vma, node); ++ else { ++ nouveau_vm_map_sg(&node->tmp_vma, 0, ++ old_mem->num_pages << PAGE_SHIFT, ++ node, node->pages); ++ } ++ } ++ + if (dev_priv->card_type < NV_50) + ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); + else +@@ -756,6 +751,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, + no_wait_gpu, new_mem); + } + ++out: + if (chan == dev_priv->channel) + mutex_unlock(&chan->mutex); + return ret; +@@ -766,6 +762,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, + bool no_wait_reserve, bool no_wait_gpu, + struct ttm_mem_reg *new_mem) + { ++ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; + struct ttm_placement placement; + struct ttm_mem_reg tmp_mem; +@@ -785,7 +782,23 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, + if (ret) + goto out; + ++ if (dev_priv->card_type >= NV_50) { ++ struct nouveau_bo *nvbo = nouveau_bo(bo); ++ struct nouveau_mem *node = tmp_mem.mm_node; ++ struct nouveau_vma *vma = &nvbo->vma; ++ if (vma->node->type != vma->vm->spg_shift) ++ vma = &node->tmp_vma; ++ nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT, ++ node, node->pages); ++ } ++ + ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem); ++ ++ if (dev_priv->card_type >= NV_50) { ++ struct nouveau_bo *nvbo = nouveau_bo(bo); ++ nouveau_vm_unmap(&nvbo->vma); ++ } ++ + if (ret) + goto out; + +@@ -828,6 +841,36 @@ out: + return ret; + } + ++static void ++nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) ++{ ++ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ struct nouveau_mem *node = new_mem->mm_node; ++ struct nouveau_bo *nvbo = nouveau_bo(bo); ++ struct nouveau_vma *vma = &nvbo->vma; ++ struct nouveau_vm *vm = vma->vm; ++ ++ if (dev_priv->card_type < NV_50) ++ return; ++ ++ switch (new_mem->mem_type) { ++ case TTM_PL_VRAM: ++ nouveau_vm_map(vma, node); ++ break; ++ case TTM_PL_TT: ++ if (vma->node->type != vm->spg_shift) { ++ nouveau_vm_unmap(vma); ++ vma = &node->tmp_vma; ++ } ++ nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT, ++ node, node->pages); ++ break; ++ default: ++ nouveau_vm_unmap(&nvbo->vma); ++ break; ++ } ++} ++ + static int + nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, + struct nouveau_tile_reg **new_tile) +@@ -835,19 +878,13 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; + struct nouveau_bo *nvbo = nouveau_bo(bo); +- uint64_t offset; ++ u64 offset = new_mem->start << PAGE_SHIFT; + +- if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { +- /* Nothing to do. */ +- *new_tile = NULL; ++ *new_tile = NULL; ++ if (new_mem->mem_type != TTM_PL_VRAM) + return 0; +- } +- +- offset = new_mem->start << PAGE_SHIFT; + +- if (dev_priv->chan_vm) { +- nouveau_vm_map(&nvbo->vma, new_mem->mm_node); +- } else if (dev_priv->card_type >= NV_10) { ++ if (dev_priv->card_type >= NV_10) { + *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, + nvbo->tile_mode, + nvbo->tile_flags); +@@ -864,11 +901,8 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; + +- if (dev_priv->card_type >= NV_10 && +- dev_priv->card_type < NV_50) { +- nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); +- *old_tile = new_tile; +- } ++ nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); ++ *old_tile = new_tile; + } + + static int +@@ -882,9 +916,11 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, + struct nouveau_tile_reg *new_tile = NULL; + int ret = 0; + +- ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); +- if (ret) +- return ret; ++ if (dev_priv->card_type < NV_50) { ++ ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); ++ if (ret) ++ return ret; ++ } + + /* Fake bo copy. */ + if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { +@@ -915,10 +951,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, + ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); + + out: +- if (ret) +- nouveau_bo_vm_cleanup(bo, NULL, &new_tile); +- else +- nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); ++ if (dev_priv->card_type < NV_50) { ++ if (ret) ++ nouveau_bo_vm_cleanup(bo, NULL, &new_tile); ++ else ++ nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); ++ } + + return ret; + } +@@ -959,7 +997,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) + break; + case TTM_PL_VRAM: + { +- struct nouveau_vram *vram = mem->mm_node; ++ struct nouveau_mem *node = mem->mm_node; + u8 page_shift; + + if (!dev_priv->bar1_vm) { +@@ -970,23 +1008,23 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) + } + + if (dev_priv->card_type == NV_C0) +- page_shift = vram->page_shift; ++ page_shift = node->page_shift; + else + page_shift = 12; + + ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, + page_shift, NV_MEM_ACCESS_RW, +- &vram->bar_vma); ++ &node->bar_vma); + if (ret) + return ret; + +- nouveau_vm_map(&vram->bar_vma, vram); ++ nouveau_vm_map(&node->bar_vma, node); + if (ret) { +- nouveau_vm_put(&vram->bar_vma); ++ nouveau_vm_put(&node->bar_vma); + return ret; + } + +- mem->bus.offset = vram->bar_vma.offset; ++ mem->bus.offset = node->bar_vma.offset; + if (dev_priv->card_type == NV_50) /*XXX*/ + mem->bus.offset -= 0x0020000000ULL; + mem->bus.base = pci_resource_start(dev->pdev, 1); +@@ -1003,16 +1041,16 @@ static void + nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); +- struct nouveau_vram *vram = mem->mm_node; ++ struct nouveau_mem *node = mem->mm_node; + + if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) + return; + +- if (!vram->bar_vma.node) ++ if (!node->bar_vma.node) + return; + +- nouveau_vm_unmap(&vram->bar_vma); +- nouveau_vm_put(&vram->bar_vma); ++ nouveau_vm_unmap(&node->bar_vma); ++ nouveau_vm_put(&node->bar_vma); + } + + static int +@@ -1062,6 +1100,7 @@ struct ttm_bo_driver nouveau_bo_driver = { + .invalidate_caches = nouveau_bo_invalidate_caches, + .init_mem_type = nouveau_bo_init_mem_type, + .evict_flags = nouveau_bo_evict_flags, ++ .move_notify = nouveau_bo_move_ntfy, + .move = nouveau_bo_move, + .verify_access = nouveau_bo_verify_access, + .sync_obj_signaled = __nouveau_fence_signalled, diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c -index 3960d66..3d7b316 100644 +index 3960d66..3837090 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -35,7 +35,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) @@ -197,11 +706,118 @@ index 3960d66..3d7b316 100644 if (dev_priv->card_type >= NV_50) { if (dev_priv->card_type < NV_C0) { +@@ -90,8 +90,7 @@ nouveau_channel_user_pushbuf_alloc(struct drm_device *dev) + else + location = TTM_PL_FLAG_TT; + +- ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false, +- true, &pushbuf); ++ ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf); + if (ret) { + NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); + return NULL; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c -index 505c6bf..566466b 100644 +index 505c6bf..764c15d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c -@@ -244,7 +244,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, +@@ -32,6 +32,7 @@ + #include "nouveau_hw.h" + #include "nouveau_crtc.h" + #include "nouveau_dma.h" ++#include "nv50_display.h" + + static void + nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) +@@ -61,18 +62,59 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { + }; + + int +-nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, +- struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo) ++nouveau_framebuffer_init(struct drm_device *dev, ++ struct nouveau_framebuffer *nv_fb, ++ struct drm_mode_fb_cmd *mode_cmd, ++ struct nouveau_bo *nvbo) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct drm_framebuffer *fb = &nv_fb->base; + int ret; + +- ret = drm_framebuffer_init(dev, &nouveau_fb->base, &nouveau_framebuffer_funcs); ++ ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs); + if (ret) { + return ret; + } + +- drm_helper_mode_fill_fb_struct(&nouveau_fb->base, mode_cmd); +- nouveau_fb->nvbo = nvbo; ++ drm_helper_mode_fill_fb_struct(fb, mode_cmd); ++ nv_fb->nvbo = nvbo; ++ ++ if (dev_priv->card_type >= NV_50) { ++ u32 tile_flags = nouveau_bo_tile_layout(nvbo); ++ if (tile_flags == 0x7a00 || ++ tile_flags == 0xfe00) ++ nv_fb->r_dma = NvEvoFB32; ++ else ++ if (tile_flags == 0x7000) ++ nv_fb->r_dma = NvEvoFB16; ++ else ++ nv_fb->r_dma = NvEvoVRAM_LP; ++ ++ switch (fb->depth) { ++ case 8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break; ++ case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break; ++ case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break; ++ case 24: ++ case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; ++ case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; ++ default: ++ NV_ERROR(dev, "unknown depth %d\n", fb->depth); ++ return -EINVAL; ++ } ++ ++ if (dev_priv->chipset == 0x50) ++ nv_fb->r_format |= (tile_flags << 8); ++ ++ if (!tile_flags) ++ nv_fb->r_pitch = 0x00100000 | fb->pitch; ++ else { ++ u32 mode = nvbo->tile_mode; ++ if (dev_priv->card_type >= NV_C0) ++ mode >>= 4; ++ nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode; ++ } ++ } ++ + return 0; + } + +@@ -182,6 +224,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, + struct nouveau_page_flip_state *s, + struct nouveau_fence **pfence) + { ++ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct drm_device *dev = chan->dev; + unsigned long flags; + int ret; +@@ -201,9 +244,12 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, + if (ret) + goto fail; + +- BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); +- OUT_RING(chan, 0); +- FIRE_RING(chan); ++ if (dev_priv->card_type < NV_C0) ++ BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); ++ else ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1); ++ OUT_RING (chan, 0); ++ FIRE_RING (chan); + + ret = nouveau_fence_new(chan, pfence, true); + if (ret) +@@ -244,7 +290,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, /* Initialize a page flip struct */ *s = (struct nouveau_page_flip_state) @@ -210,6 +826,85 @@ index 505c6bf..566466b 100644 fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, new_bo->bo.offset }; +@@ -255,6 +301,14 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + mutex_lock(&chan->mutex); + + /* Emit a page flip */ ++ if (dev_priv->card_type >= NV_50) { ++ ret = nv50_display_flip_next(crtc, fb, chan); ++ if (ret) { ++ nouveau_channel_put(&chan); ++ goto fail_unreserve; ++ } ++ } ++ + ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); + nouveau_channel_put(&chan); + if (ret) +@@ -305,7 +359,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, + } + + list_del(&s->head); +- *ps = *s; ++ if (ps) ++ *ps = *s; + kfree(s); + + spin_unlock_irqrestore(&dev->event_lock, flags); +diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c +index b368ed7..ce38e97 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_dma.c ++++ b/drivers/gpu/drm/nouveau/nouveau_dma.c +@@ -97,13 +97,15 @@ nouveau_dma_init(struct nouveau_channel *chan) + OUT_RING(chan, 0); + + /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ +- ret = RING_SPACE(chan, 4); ++ ret = RING_SPACE(chan, 6); + if (ret) + return ret; + BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); +- OUT_RING(chan, NvM2MF); +- BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); +- OUT_RING(chan, NvNotify0); ++ OUT_RING (chan, NvM2MF); ++ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); ++ OUT_RING (chan, NvNotify0); ++ OUT_RING (chan, chan->vram_handle); ++ OUT_RING (chan, chan->gart_handle); + + /* Sit back and pray the channel works.. */ + FIRE_RING(chan); +diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h +index c36f176..23d4edf 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_dma.h ++++ b/drivers/gpu/drm/nouveau/nouveau_dma.h +@@ -61,8 +61,6 @@ enum { + NvM2MF = 0x80000001, + NvDmaFB = 0x80000002, + NvDmaTT = 0x80000003, +- NvDmaVRAM = 0x80000004, +- NvDmaGART = 0x80000005, + NvNotify0 = 0x80000006, + Nv2D = 0x80000007, + NvCtxSurf2D = 0x80000008, +@@ -73,12 +71,15 @@ enum { + NvImageBlit = 0x8000000d, + NvSw = 0x8000000e, + NvSema = 0x8000000f, ++ NvEvoSema0 = 0x80000010, ++ NvEvoSema1 = 0x80000011, + + /* G80+ display objects */ + NvEvoVRAM = 0x01000000, + NvEvoFB16 = 0x01000001, + NvEvoFB32 = 0x01000002, +- NvEvoVRAM_LP = 0x01000003 ++ NvEvoVRAM_LP = 0x01000003, ++ NvEvoSync = 0xcafe0000 + }; + + #define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 38d5995..7beb82a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -231,18 +926,98 @@ index 38d5995..7beb82a 100644 ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index 982d70b..2cae8e7 100644 +index 982d70b..e172d72 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -652,7 +652,6 @@ struct drm_nouveau_private { +@@ -57,7 +57,7 @@ struct nouveau_fpriv { + #include "nouveau_util.h" + + struct nouveau_grctx; +-struct nouveau_vram; ++struct nouveau_mem; + #include "nouveau_vm.h" + + #define MAX_NUM_DCB_ENTRIES 16 +@@ -65,13 +65,16 @@ struct nouveau_vram; + #define NOUVEAU_MAX_CHANNEL_NR 128 + #define NOUVEAU_MAX_TILE_NR 15 + +-struct nouveau_vram { ++struct nouveau_mem { + struct drm_device *dev; + + struct nouveau_vma bar_vma; ++ struct nouveau_vma tmp_vma; + u8 page_shift; + ++ struct drm_mm_node *tag; + struct list_head regions; ++ dma_addr_t *pages; + u32 memtype; + u64 offset; + u64 size; +@@ -90,6 +93,7 @@ struct nouveau_tile_reg { + struct nouveau_bo { + struct ttm_buffer_object bo; + struct ttm_placement placement; ++ u32 valid_domains; + u32 placements[3]; + u32 busy_placements[3]; + struct ttm_bo_kmap_obj kmap; +@@ -104,8 +108,6 @@ struct nouveau_bo { + struct nouveau_channel *channel; + + struct nouveau_vma vma; +- bool mappable; +- bool no_vm; + + uint32_t tile_mode; + uint32_t tile_flags; +@@ -387,6 +389,7 @@ struct nouveau_pgraph_engine { + }; + + struct nouveau_display_engine { ++ void *priv; + int (*early_init)(struct drm_device *); + void (*late_takedown)(struct drm_device *); + int (*create)(struct drm_device *); +@@ -463,6 +466,7 @@ struct nouveau_pm_memtiming { + u32 reg_100234; + u32 reg_100238; + u32 reg_10023c; ++ u32 reg_100240; + }; + + struct nouveau_pm_memtimings { +@@ -509,8 +513,8 @@ struct nouveau_crypt_engine { + struct nouveau_vram_engine { + int (*init)(struct drm_device *); + int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, +- u32 type, struct nouveau_vram **); +- void (*put)(struct drm_device *, struct nouveau_vram **); ++ u32 type, struct nouveau_mem **); ++ void (*put)(struct drm_device *, struct nouveau_mem **); + + bool (*flags_valid)(struct drm_device *, u32 tile_flags); + }; +@@ -634,6 +638,7 @@ struct drm_nouveau_private { + enum nouveau_card_type card_type; + /* exact chipset, derived from NV_PMC_BOOT_0 */ + int chipset; ++ int stepping; + int flags; + + void __iomem *mmio; +@@ -652,8 +657,6 @@ struct drm_nouveau_private { /* interrupt handling */ void (*irq_handler[32])(struct drm_device *); bool msi_enabled; - struct workqueue_struct *wq; - struct work_struct irq_work; +- struct work_struct irq_work; struct list_head vbl_waiting; -@@ -691,13 +690,21 @@ struct drm_nouveau_private { + +@@ -691,15 +694,22 @@ struct drm_nouveau_private { struct { enum { NOUVEAU_GART_NONE = 0, @@ -264,9 +1039,65 @@ index 982d70b..2cae8e7 100644 + } dummy; + struct nouveau_gpuobj *sg_ctxdma; - struct nouveau_vma vma; +- struct nouveau_vma vma; } gart_info; -@@ -1076,7 +1083,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); + + /* nv10-nv40 tiling regions */ +@@ -740,14 +750,6 @@ struct drm_nouveau_private { + + struct backlight_device *backlight; + +- struct nouveau_channel *evo; +- u32 evo_alloc; +- struct { +- struct dcb_entry *dcb; +- u16 script; +- u32 pclk; +- } evo_irq; +- + struct { + struct dentry *channel_root; + } debugfs; +@@ -847,6 +849,7 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, + struct nouveau_tile_reg *tile, + struct nouveau_fence *fence); + extern const struct ttm_mem_type_manager_func nouveau_vram_manager; ++extern const struct ttm_mem_type_manager_func nouveau_gart_manager; + + /* nouveau_notifier.c */ + extern int nouveau_notifier_init_channel(struct nouveau_channel *); +@@ -879,17 +882,17 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan, + extern void nouveau_channel_idle(struct nouveau_channel *chan); + + /* nouveau_object.c */ +-#define NVOBJ_CLASS(d,c,e) do { \ ++#define NVOBJ_CLASS(d, c, e) do { \ + int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ + if (ret) \ + return ret; \ +-} while(0) ++} while (0) + +-#define NVOBJ_MTHD(d,c,m,e) do { \ ++#define NVOBJ_MTHD(d, c, m, e) do { \ + int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \ + if (ret) \ + return ret; \ +-} while(0) ++} while (0) + + extern int nouveau_gpuobj_early_init(struct drm_device *); + extern int nouveau_gpuobj_init(struct drm_device *); +@@ -899,7 +902,7 @@ extern void nouveau_gpuobj_resume(struct drm_device *dev); + extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); + extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, + int (*exec)(struct nouveau_channel *, +- u32 class, u32 mthd, u32 data)); ++ u32 class, u32 mthd, u32 data)); + extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); + extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); + extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, +@@ -1076,7 +1079,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); /* nv50_fb.c */ extern int nv50_fb_init(struct drm_device *); extern void nv50_fb_takedown(struct drm_device *); @@ -275,8 +1106,67 @@ index 982d70b..2cae8e7 100644 /* nvc0_fb.c */ extern int nvc0_fb_init(struct drm_device *); +@@ -1189,7 +1192,7 @@ extern int nv50_graph_load_context(struct nouveau_channel *); + extern int nv50_graph_unload_context(struct drm_device *); + extern int nv50_grctx_init(struct nouveau_grctx *); + extern void nv50_graph_tlb_flush(struct drm_device *dev); +-extern void nv86_graph_tlb_flush(struct drm_device *dev); ++extern void nv84_graph_tlb_flush(struct drm_device *dev); + extern struct nouveau_enum nv50_data_error_names[]; + + /* nvc0_graph.c */ +@@ -1295,7 +1298,7 @@ extern struct ttm_bo_driver nouveau_bo_driver; + extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, + int size, int align, uint32_t flags, + uint32_t tile_mode, uint32_t tile_flags, +- bool no_vm, bool mappable, struct nouveau_bo **); ++ struct nouveau_bo **); + extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); + extern int nouveau_bo_unpin(struct nouveau_bo *); + extern int nouveau_bo_map(struct nouveau_bo *); +@@ -1356,9 +1359,9 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) + + /* nouveau_gem.c */ + extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, +- int size, int align, uint32_t flags, ++ int size, int align, uint32_t domain, + uint32_t tile_mode, uint32_t tile_flags, +- bool no_vm, bool mappable, struct nouveau_bo **); ++ struct nouveau_bo **); + extern int nouveau_gem_object_new(struct drm_gem_object *); + extern void nouveau_gem_object_del(struct drm_gem_object *); + extern int nouveau_gem_ioctl_new(struct drm_device *, void *, +diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h +index d432134..a3a88ad 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fb.h ++++ b/drivers/gpu/drm/nouveau/nouveau_fb.h +@@ -30,6 +30,9 @@ + struct nouveau_framebuffer { + struct drm_framebuffer base; + struct nouveau_bo *nvbo; ++ u32 r_dma; ++ u32 r_format; ++ u32 r_pitch; + }; + + static inline struct nouveau_framebuffer * +diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +index 60769d2..889c445 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c ++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c +@@ -296,8 +296,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, + size = mode_cmd.pitch * mode_cmd.height; + size = roundup(size, PAGE_SIZE); + +- ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nvbo); ++ ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, ++ NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); + if (ret) { + NV_ERROR(dev, "failed to allocate framebuffer\n"); + goto out; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c -index 221b846..594911f 100644 +index 221b846..4b9f449 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -27,13 +27,15 @@ @@ -614,7 +1504,7 @@ index 221b846..594911f 100644 return 0; } -@@ -519,11 +581,12 @@ int +@@ -519,12 +581,13 @@ int nouveau_fence_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -624,15 +1514,184 @@ index 221b846..594911f 100644 /* Create a shared VRAM heap for cross-channel sync. */ if (USE_SEMA(dev)) { - ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, +- 0, 0, false, true, &dev_priv->fence.bo); + ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM, - 0, 0, false, true, &dev_priv->fence.bo); ++ 0, 0, &dev_priv->fence.bo); if (ret) return ret; + +diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c +index 506c508..e8b04f4 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_gem.c ++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c +@@ -61,19 +61,36 @@ nouveau_gem_object_del(struct drm_gem_object *gem) + + int + nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, +- int size, int align, uint32_t flags, uint32_t tile_mode, +- uint32_t tile_flags, bool no_vm, bool mappable, +- struct nouveau_bo **pnvbo) ++ int size, int align, uint32_t domain, uint32_t tile_mode, ++ uint32_t tile_flags, struct nouveau_bo **pnvbo) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *nvbo; ++ u32 flags = 0; + int ret; + ++ if (domain & NOUVEAU_GEM_DOMAIN_VRAM) ++ flags |= TTM_PL_FLAG_VRAM; ++ if (domain & NOUVEAU_GEM_DOMAIN_GART) ++ flags |= TTM_PL_FLAG_TT; ++ if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) ++ flags |= TTM_PL_FLAG_SYSTEM; ++ + ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, +- tile_flags, no_vm, mappable, pnvbo); ++ tile_flags, pnvbo); + if (ret) + return ret; + nvbo = *pnvbo; + ++ /* we restrict allowed domains on nv50+ to only the types ++ * that were requested at creation time. not possibly on ++ * earlier chips without busting the ABI. ++ */ ++ nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | ++ NOUVEAU_GEM_DOMAIN_GART; ++ if (dev_priv->card_type >= NV_50) ++ nvbo->valid_domains &= domain; ++ + nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); + if (!nvbo->gem) { + nouveau_bo_ref(NULL, pnvbo); +@@ -97,7 +114,7 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) + + rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; + rep->offset = nvbo->bo.offset; +- rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0; ++ rep->map_handle = nvbo->bo.addr_space_offset; + rep->tile_mode = nvbo->tile_mode; + rep->tile_flags = nvbo->tile_flags; + return 0; +@@ -111,19 +128,11 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, + struct drm_nouveau_gem_new *req = data; + struct nouveau_bo *nvbo = NULL; + struct nouveau_channel *chan = NULL; +- uint32_t flags = 0; + int ret = 0; + + if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) + dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; + +- if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) +- flags |= TTM_PL_FLAG_VRAM; +- if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) +- flags |= TTM_PL_FLAG_TT; +- if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) +- flags |= TTM_PL_FLAG_SYSTEM; +- + if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { + NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); + return -EINVAL; +@@ -135,10 +144,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, + return PTR_ERR(chan); + } + +- ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, +- req->info.tile_mode, req->info.tile_flags, false, +- (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), +- &nvbo); ++ ret = nouveau_gem_new(dev, chan, req->info.size, req->align, ++ req->info.domain, req->info.tile_mode, ++ req->info.tile_flags, &nvbo); + if (chan) + nouveau_channel_put(&chan); + if (ret) +@@ -161,7 +169,7 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, + { + struct nouveau_bo *nvbo = gem->driver_private; + struct ttm_buffer_object *bo = &nvbo->bo; +- uint32_t domains = valid_domains & ++ uint32_t domains = valid_domains & nvbo->valid_domains & + (write_domains ? write_domains : read_domains); + uint32_t pref_flags = 0, valid_flags = 0; + +@@ -592,7 +600,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, + if (push[i].bo_index >= req->nr_buffers) { + NV_ERROR(dev, "push %d buffer not in list\n", i); + ret = -EINVAL; +- goto out; ++ goto out_prevalid; + } + + bo[push[i].bo_index].read_domains |= (1 << 31); +@@ -604,7 +612,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, + if (ret) { + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "validate: %d\n", ret); +- goto out; ++ goto out_prevalid; + } + + /* Apply any relocations that are required */ +@@ -697,6 +705,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, + out: + validate_fini(&op, fence); + nouveau_fence_unref(&fence); ++ ++out_prevalid: + kfree(bo); + kfree(push); + +diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h +index 4a8ad13..86c2e37 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_grctx.h ++++ b/drivers/gpu/drm/nouveau/nouveau_grctx.h +@@ -87,10 +87,10 @@ _cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name) + cp_out(ctx, CP_BRA | (mod << 18) | ip | flag | + (state ? 0 : CP_BRA_IF_CLEAR)); + } +-#define cp_bra(c,f,s,n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n) ++#define cp_bra(c, f, s, n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n) + #ifdef CP_BRA_MOD +-#define cp_cal(c,f,s,n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n) +-#define cp_ret(c,f,s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0) ++#define cp_cal(c, f, s, n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n) ++#define cp_ret(c, f, s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0) + #endif + + static inline void +@@ -98,14 +98,14 @@ _cp_wait(struct nouveau_grctx *ctx, int flag, int state) + { + cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0)); + } +-#define cp_wait(c,f,s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s) ++#define cp_wait(c, f, s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s) + + static inline void + _cp_set(struct nouveau_grctx *ctx, int flag, int state) + { + cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0)); + } +-#define cp_set(c,f,s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s) ++#define cp_set(c, f, s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s) + + static inline void + cp_pos(struct nouveau_grctx *ctx, int offset) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index b0fb9bd..5b769eb 100644 +index b0fb9bd..9a91bf1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c -@@ -393,11 +393,17 @@ nouveau_mem_vram_init(struct drm_device *dev) +@@ -152,7 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + +- nouveau_bo_unpin(dev_priv->vga_ram); + nouveau_bo_ref(NULL, &dev_priv->vga_ram); + + ttm_bo_device_release(&dev_priv->ttm.bdev); +@@ -393,11 +392,17 @@ nouveau_mem_vram_init(struct drm_device *dev) struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; int ret, dma_bits; @@ -655,7 +1714,7 @@ index b0fb9bd..5b769eb 100644 ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); if (ret) -@@ -419,14 +425,32 @@ nouveau_mem_vram_init(struct drm_device *dev) +@@ -419,14 +424,32 @@ nouveau_mem_vram_init(struct drm_device *dev) } /* reserve space at end of VRAM for PRAMIN */ @@ -696,11 +1755,382 @@ index b0fb9bd..5b769eb 100644 ret = dev_priv->engine.vram.init(dev); if (ret) +@@ -455,13 +478,17 @@ nouveau_mem_vram_init(struct drm_device *dev) + return ret; + } + +- ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, +- 0, 0, true, true, &dev_priv->vga_ram); +- if (ret == 0) +- ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM); +- if (ret) { +- NV_WARN(dev, "failed to reserve VGA memory\n"); +- nouveau_bo_ref(NULL, &dev_priv->vga_ram); ++ if (dev_priv->card_type < NV_50) { ++ ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, ++ 0, 0, &dev_priv->vga_ram); ++ if (ret == 0) ++ ret = nouveau_bo_pin(dev_priv->vga_ram, ++ TTM_PL_FLAG_VRAM); ++ ++ if (ret) { ++ NV_WARN(dev, "failed to reserve VGA memory\n"); ++ nouveau_bo_ref(NULL, &dev_priv->vga_ram); ++ } + } + + dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), +@@ -525,6 +552,7 @@ nouveau_mem_timing_init(struct drm_device *dev) + u8 tRC; /* Byte 9 */ + u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; + u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; ++ u8 magic_number = 0; /* Yeah... sorry*/ + u8 *mem = NULL, *entry; + int i, recordlen, entries; + +@@ -569,6 +597,12 @@ nouveau_mem_timing_init(struct drm_device *dev) + if (!memtimings->timing) + return; + ++ /* Get "some number" from the timing reg for NV_40 and NV_50 ++ * Used in calculations later */ ++ if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) { ++ magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; ++ } ++ + entry = mem + mem[1]; + for (i = 0; i < entries; i++, entry += recordlen) { + struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; +@@ -608,36 +642,67 @@ nouveau_mem_timing_init(struct drm_device *dev) + + /* XXX: I don't trust the -1's and +1's... they must come + * from somewhere! */ +- timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 | +- tUNK_18 << 16 | +- (tUNK_1 + tUNK_19 + 1) << 8 | +- (tUNK_2 - 1)); ++ timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 | ++ max(tUNK_18, (u8) 1) << 16 | ++ (tUNK_1 + tUNK_19 + 1 + magic_number) << 8; ++ if (dev_priv->chipset == 0xa8) { ++ timing->reg_100224 |= (tUNK_2 - 1); ++ } else { ++ timing->reg_100224 |= (tUNK_2 + 2 - magic_number); ++ } + + timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); +- if(recordlen > 19) { +- timing->reg_100228 += (tUNK_19 - 1) << 24; +- }/* I cannot back-up this else-statement right now +- else { +- timing->reg_100228 += tUNK_12 << 24; +- }*/ +- +- /* XXX: reg_10022c */ +- timing->reg_10022c = tUNK_2 - 1; +- +- timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | +- tUNK_13 << 8 | tUNK_13); +- +- /* XXX: +6? */ +- timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC); +- timing->reg_100234 += max(tUNK_10,tUNK_11) << 16; +- +- /* XXX; reg_100238, reg_10023c +- * reg: 0x00?????? +- * reg_10023c: +- * 0 for pre-NV50 cards +- * 0x????0202 for NV50+ cards (empirical evidence) */ +- if(dev_priv->card_type >= NV_50) { ++ if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) ++ timing->reg_100228 |= (tUNK_19 - 1) << 24; ++ else ++ timing->reg_100228 |= magic_number << 24; ++ ++ if (dev_priv->card_type == NV_40) { ++ /* NV40: don't know what the rest of the regs are.. ++ * And don't need to know either */ ++ timing->reg_100228 |= 0x20200000; ++ } else if (dev_priv->card_type >= NV_50) { ++ if (dev_priv->chipset < 0x98 || ++ (dev_priv->chipset == 0x98 && ++ dev_priv->stepping <= 0xa1)) { ++ timing->reg_10022c = (0x14 + tUNK_2) << 24 | ++ 0x16 << 16 | ++ (tUNK_2 - 1) << 8 | ++ (tUNK_2 - 1); ++ } else { ++ /* XXX: reg_10022c for recentish cards */ ++ timing->reg_10022c = tUNK_2 - 1; ++ } ++ ++ timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | ++ tUNK_13 << 8 | tUNK_13); ++ ++ timing->reg_100234 = (tRAS << 24 | tRC); ++ timing->reg_100234 += max(tUNK_10, tUNK_11) << 16; ++ ++ if (dev_priv->chipset < 0x98 || ++ (dev_priv->chipset == 0x98 && ++ dev_priv->stepping <= 0xa1)) { ++ timing->reg_100234 |= (tUNK_2 + 2) << 8; ++ } else { ++ /* XXX: +6? */ ++ timing->reg_100234 |= (tUNK_19 + 6) << 8; ++ } ++ ++ /* XXX; reg_100238 ++ * reg_100238: 0x00?????? */ + timing->reg_10023c = 0x202; ++ if (dev_priv->chipset < 0x98 || ++ (dev_priv->chipset == 0x98 && ++ dev_priv->stepping <= 0xa1)) { ++ timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16; ++ } else { ++ /* XXX: reg_10023c ++ * currently unknown ++ * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ ++ } ++ ++ /* XXX: reg_100240? */ + } + + NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, +@@ -646,9 +711,10 @@ nouveau_mem_timing_init(struct drm_device *dev) + NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", + timing->reg_100230, timing->reg_100234, + timing->reg_100238, timing->reg_10023c); ++ NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240); + } + +- memtimings->nr_timing = entries; ++ memtimings->nr_timing = entries; + memtimings->supported = true; + } + +@@ -666,13 +732,14 @@ nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_mm *mm; +- u32 b_size; ++ u64 size, block, rsvd; + int ret; + +- p_size = (p_size << PAGE_SHIFT) >> 12; +- b_size = dev_priv->vram_rblock_size >> 12; ++ rsvd = (256 * 1024); /* vga memory */ ++ size = (p_size << PAGE_SHIFT) - rsvd; ++ block = dev_priv->vram_rblock_size; + +- ret = nouveau_mm_init(&mm, 0, p_size, b_size); ++ ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12); + if (ret) + return ret; + +@@ -700,9 +767,15 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, + { + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; ++ struct nouveau_mem *node = mem->mm_node; + struct drm_device *dev = dev_priv->dev; + +- vram->put(dev, (struct nouveau_vram **)&mem->mm_node); ++ if (node->tmp_vma.node) { ++ nouveau_vm_unmap(&node->tmp_vma); ++ nouveau_vm_put(&node->tmp_vma); ++ } ++ ++ vram->put(dev, (struct nouveau_mem **)&mem->mm_node); + } + + static int +@@ -715,7 +788,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct drm_device *dev = dev_priv->dev; + struct nouveau_bo *nvbo = nouveau_bo(bo); +- struct nouveau_vram *node; ++ struct nouveau_mem *node; + u32 size_nc = 0; + int ret; + +@@ -724,7 +797,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, + + ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, +- (nvbo->tile_flags >> 8) & 0xff, &node); ++ (nvbo->tile_flags >> 8) & 0x3ff, &node); + if (ret) { + mem->mm_node = NULL; + return (ret == -ENOSPC) ? 0 : ret; +@@ -771,3 +844,84 @@ const struct ttm_mem_type_manager_func nouveau_vram_manager = { + nouveau_vram_manager_del, + nouveau_vram_manager_debug + }; ++ ++static int ++nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) ++{ ++ return 0; ++} ++ ++static int ++nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) ++{ ++ return 0; ++} ++ ++static void ++nouveau_gart_manager_del(struct ttm_mem_type_manager *man, ++ struct ttm_mem_reg *mem) ++{ ++ struct nouveau_mem *node = mem->mm_node; ++ ++ if (node->tmp_vma.node) { ++ nouveau_vm_unmap(&node->tmp_vma); ++ nouveau_vm_put(&node->tmp_vma); ++ } ++ mem->mm_node = NULL; ++} ++ ++static int ++nouveau_gart_manager_new(struct ttm_mem_type_manager *man, ++ struct ttm_buffer_object *bo, ++ struct ttm_placement *placement, ++ struct ttm_mem_reg *mem) ++{ ++ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ struct nouveau_bo *nvbo = nouveau_bo(bo); ++ struct nouveau_vma *vma = &nvbo->vma; ++ struct nouveau_vm *vm = vma->vm; ++ struct nouveau_mem *node; ++ int ret; ++ ++ if (unlikely((mem->num_pages << PAGE_SHIFT) >= ++ dev_priv->gart_info.aper_size)) ++ return -ENOMEM; ++ ++ node = kzalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) ++ return -ENOMEM; ++ ++ /* This node must be for evicting large-paged VRAM ++ * to system memory. Due to a nv50 limitation of ++ * not being able to mix large/small pages within ++ * the same PDE, we need to create a temporary ++ * small-paged VMA for the eviction. ++ */ ++ if (vma->node->type != vm->spg_shift) { ++ ret = nouveau_vm_get(vm, (u64)vma->node->length << 12, ++ vm->spg_shift, NV_MEM_ACCESS_RW, ++ &node->tmp_vma); ++ if (ret) { ++ kfree(node); ++ return ret; ++ } ++ } ++ ++ node->page_shift = nvbo->vma.node->type; ++ mem->mm_node = node; ++ mem->start = 0; ++ return 0; ++} ++ ++void ++nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) ++{ ++} ++ ++const struct ttm_mem_type_manager_func nouveau_gart_manager = { ++ nouveau_gart_manager_init, ++ nouveau_gart_manager_fini, ++ nouveau_gart_manager_new, ++ nouveau_gart_manager_del, ++ nouveau_gart_manager_debug ++}; +diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h +index 798eaf3..1f7483a 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_mm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_mm.h +@@ -53,13 +53,13 @@ void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); + + int nv50_vram_init(struct drm_device *); + int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, +- u32 memtype, struct nouveau_vram **); +-void nv50_vram_del(struct drm_device *, struct nouveau_vram **); ++ u32 memtype, struct nouveau_mem **); ++void nv50_vram_del(struct drm_device *, struct nouveau_mem **); + bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); + + int nvc0_vram_init(struct drm_device *); + int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, +- u32 memtype, struct nouveau_vram **); ++ u32 memtype, struct nouveau_mem **); + bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); + + #endif +diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c +index 5ea1676..7ba3fc0 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_notifier.c ++++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c +@@ -39,12 +39,11 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) + int ret; + + if (nouveau_vram_notify) +- flags = TTM_PL_FLAG_VRAM; ++ flags = NOUVEAU_GEM_DOMAIN_VRAM; + else +- flags = TTM_PL_FLAG_TT; ++ flags = NOUVEAU_GEM_DOMAIN_GART; + +- ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, +- 0, 0x0000, false, true, &ntfy); ++ ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy); + if (ret) + return ret; + +@@ -100,6 +99,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, + uint32_t *b_offset) + { + struct drm_device *dev = chan->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *nobj = NULL; + struct drm_mm_node *mem; + uint32_t offset; +@@ -114,11 +114,16 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, + return -ENOMEM; + } + +- if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) +- target = NV_MEM_TARGET_VRAM; +- else +- target = NV_MEM_TARGET_GART; +- offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; ++ if (dev_priv->card_type < NV_50) { ++ if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) ++ target = NV_MEM_TARGET_VRAM; ++ else ++ target = NV_MEM_TARGET_GART; ++ offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; ++ } else { ++ target = NV_MEM_TARGET_VM; ++ offset = chan->notifier_bo->vma.offset; ++ } + offset += mem->start; + + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c -index 30b6544..3c12461 100644 +index 30b6544..823800d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c -@@ -490,16 +490,22 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, +@@ -36,6 +36,7 @@ + #include "nouveau_drm.h" + #include "nouveau_ramht.h" + #include "nouveau_vm.h" ++#include "nv50_display.h" + + struct nouveau_gpuobj_method { + struct list_head head; +@@ -490,16 +491,22 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, } if (target == NV_MEM_TARGET_GART) { @@ -731,6 +2161,41 @@ index 30b6544..3c12461 100644 } } +@@ -776,7 +783,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *vram = NULL, *tt = NULL; +- int ret; ++ int ret, i; + + NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); + +@@ -841,6 +848,25 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, + nouveau_gpuobj_ref(NULL, &ramht); + if (ret) + return ret; ++ ++ /* dma objects for display sync channel semaphore blocks */ ++ for (i = 0; i < 2; i++) { ++ struct nouveau_gpuobj *sem = NULL; ++ struct nv50_display_crtc *dispc = ++ &nv50_display(dev)->crtc[i]; ++ u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; ++ ++ ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff, ++ NV_MEM_ACCESS_RW, ++ NV_MEM_TARGET_VRAM, &sem); ++ if (ret) ++ return ret; ++ ++ ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, sem); ++ nouveau_gpuobj_ref(NULL, &sem); ++ if (ret) ++ return ret; ++ } + } + + /* VRAM ctxdma */ diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index ac62a1b..670e3cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -744,8 +2209,75 @@ index ac62a1b..670e3cb 100644 perflvl->core = ROM32(entry[1]) * 10; perflvl->memory = ROM32(entry[5]) * 20; break; +diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c +index 4399e2f..0b1caeb 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_pm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_pm.c +@@ -490,6 +490,7 @@ nouveau_pm_init(struct drm_device *dev) + /* determine current ("boot") performance level */ + ret = nouveau_pm_perflvl_get(dev, &pm->boot); + if (ret == 0) { ++ strncpy(pm->boot.name, "boot", 4); + pm->cur = &pm->boot; + + nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); +diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c +index bef3e69..a24a81f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_ramht.c ++++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c +@@ -114,7 +114,9 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, + (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); + } else { + if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { +- ctx = (gpuobj->cinst << 10) | chan->id; ++ ctx = (gpuobj->cinst << 10) | ++ (chan->id << 28) | ++ chan->id; /* HASH_TAG */ + } else { + ctx = (gpuobj->cinst >> 4) | + ((gpuobj->engine << +diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h +index 04e8fb7..f18cdfc 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_reg.h ++++ b/drivers/gpu/drm/nouveau/nouveau_reg.h +@@ -639,9 +639,9 @@ + # define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240 + # define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258 + +-#define NV50_AUXCH_DATA_OUT(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4c0) ++#define NV50_AUXCH_DATA_OUT(i, n) ((n) * 4 + (i) * 0x50 + 0x0000e4c0) + #define NV50_AUXCH_DATA_OUT__SIZE 4 +-#define NV50_AUXCH_DATA_IN(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4d0) ++#define NV50_AUXCH_DATA_IN(i, n) ((n) * 4 + (i) * 0x50 + 0x0000e4d0) + #define NV50_AUXCH_DATA_IN__SIZE 4 + #define NV50_AUXCH_ADDR(i) ((i) * 0x50 + 0x0000e4e0) + #define NV50_AUXCH_CTRL(i) ((i) * 0x50 + 0x0000e4e4) +@@ -829,7 +829,7 @@ + #define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084 + #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 + #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff +-#define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) ++#define NV50_SOR_DP_CTRL(i, l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) + #define NV50_SOR_DP_CTRL_ENABLED 0x00000001 + #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 + #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 +@@ -841,10 +841,10 @@ + #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_DISABLED 0x00000000 + #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_1 0x01000000 + #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000 +-#define NV50_SOR_DP_UNK118(i,l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) +-#define NV50_SOR_DP_UNK120(i,l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) +-#define NV50_SOR_DP_UNK128(i,l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) +-#define NV50_SOR_DP_UNK130(i,l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) ++#define NV50_SOR_DP_UNK118(i, l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) ++#define NV50_SOR_DP_UNK120(i, l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) ++#define NV50_SOR_DP_UNK128(i, l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) ++#define NV50_SOR_DP_UNK130(i, l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) + + #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) + #define NV50_PDISPLAY_USER_PUT(i) ((i) * 0x1000 + 0x00640000) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 9a250eb..a26383b 100644 +index 9a250eb..b410d31 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -74,8 +74,24 @@ nouveau_sgdma_clear(struct ttm_backend *be) @@ -783,7 +2315,7 @@ index 9a250eb..a26383b 100644 { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; struct drm_device *dev = nvbe->dev; -@@ -125,23 +141,222 @@ nouveau_sgdma_unbind(struct ttm_backend *be) +@@ -125,59 +141,245 @@ nouveau_sgdma_unbind(struct ttm_backend *be) return 0; } @@ -927,18 +2459,21 @@ index 9a250eb..a26383b 100644 } static int +-nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) +nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; + dma_addr_t *list = nvbe->pages; + u32 pte = mem->start << 2, tmp[4]; + u32 cnt = nvbe->nr_pages; + int i; -+ -+ nvbe->offset = mem->start << PAGE_SHIFT; -+ + + nvbe->offset = mem->start << PAGE_SHIFT; + +- nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset, +- nvbe->nr_pages << PAGE_SHIFT, nvbe->pages); + if (pte & 0x0000000c) { + u32 max = 4 - ((pte >> 2) & 0x3); + u32 part = (cnt > max) ? max : cnt; @@ -963,15 +2498,16 @@ index 9a250eb..a26383b 100644 + nv44_sgdma_fill(pgt, list, pte, cnt); + + nv44_sgdma_flush(nvbe); -+ nvbe->bound = true; -+ return 0; -+} -+ -+static int + nvbe->bound = true; + return 0; + } + + static int +-nv50_sgdma_unbind(struct ttm_backend *be) +nv44_sgdma_unbind(struct ttm_backend *be) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + { + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; + u32 pte = (nvbe->offset >> 12) << 2; + u32 cnt = nvbe->nr_pages; @@ -983,7 +2519,9 @@ index 9a250eb..a26383b 100644 + pte += (part << 2); + cnt -= part; + } -+ + +- if (!nvbe->bound) +- return 0; + while (cnt >= 4) { + nv_wo32(pgt, pte + 0x0, 0x00000000); + nv_wo32(pgt, pte + 0x4, 0x00000000); @@ -992,43 +2530,56 @@ index 9a250eb..a26383b 100644 + pte += 0x10; + cnt -= 4; + } -+ + +- nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset, +- nvbe->nr_pages << PAGE_SHIFT); + if (cnt) + nv44_sgdma_fill(pgt, NULL, pte, cnt); + + nv44_sgdma_flush(nvbe); -+ nvbe->bound = false; -+ return 0; -+} -+ -+static struct ttm_backend_func nv44_sgdma_backend = { -+ .populate = nouveau_sgdma_populate, -+ .clear = nouveau_sgdma_clear, -+ .bind = nv44_sgdma_bind, -+ .unbind = nv44_sgdma_unbind, -+ .destroy = nouveau_sgdma_destroy -+}; -+ -+static int - nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -@@ -170,14 +385,6 @@ nv50_sgdma_unbind(struct ttm_backend *be) + nvbe->bound = false; return 0; } -static struct ttm_backend_func nouveau_sgdma_backend = { -- .populate = nouveau_sgdma_populate, -- .clear = nouveau_sgdma_clear, ++static struct ttm_backend_func nv44_sgdma_backend = { + .populate = nouveau_sgdma_populate, + .clear = nouveau_sgdma_clear, - .bind = nouveau_sgdma_bind, - .unbind = nouveau_sgdma_unbind, -- .destroy = nouveau_sgdma_destroy --}; -- ++ .bind = nv44_sgdma_bind, ++ .unbind = nv44_sgdma_unbind, + .destroy = nouveau_sgdma_destroy + }; + ++static int ++nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ++{ ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_mem *node = mem->mm_node; ++ /* noop: bound in move_notify() */ ++ node->pages = nvbe->pages; ++ nvbe->pages = (dma_addr_t *)node; ++ nvbe->bound = true; ++ return 0; ++} ++ ++static int ++nv50_sgdma_unbind(struct ttm_backend *be) ++{ ++ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; ++ struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages; ++ /* noop: unbound in move_notify() */ ++ nvbe->pages = node->pages; ++ node->pages = NULL; ++ nvbe->bound = false; ++ return 0; ++} ++ static struct ttm_backend_func nv50_sgdma_backend = { .populate = nouveau_sgdma_populate, .clear = nouveau_sgdma_clear, -@@ -198,10 +405,7 @@ nouveau_sgdma_init_ttm(struct drm_device *dev) +@@ -198,10 +400,7 @@ nouveau_sgdma_init_ttm(struct drm_device *dev) nvbe->dev = dev; @@ -1040,7 +2591,7 @@ index 9a250eb..a26383b 100644 return &nvbe->backend; } -@@ -210,21 +414,70 @@ nouveau_sgdma_init(struct drm_device *dev) +@@ -210,21 +409,64 @@ nouveau_sgdma_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *gpuobj = NULL; @@ -1048,7 +2599,12 @@ index 9a250eb..a26383b 100644 - int i, ret; + u32 aper_size, align; + int ret; -+ + +- if (dev_priv->card_type < NV_50) { +- if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) +- aper_size = 64 * 1024 * 1024; +- else +- aper_size = 512 * 1024 * 1024; + if (dev_priv->card_type >= NV_50 || drm_device_is_pcie(dev)) + aper_size = 512 * 1024 * 1024; + else @@ -1061,7 +2617,9 @@ index 9a250eb..a26383b 100644 + dev_priv->gart_info.dummy.page = alloc_page(GFP_DMA32 | GFP_KERNEL); + if (!dev_priv->gart_info.dummy.page) + return -ENOMEM; -+ + +- obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; +- obj_size += 8; /* ctxdma header */ + dev_priv->gart_info.dummy.addr = + pci_map_page(dev->pdev, dev_priv->gart_info.dummy.page, + 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); @@ -1072,19 +2630,11 @@ index 9a250eb..a26383b 100644 + return -ENOMEM; + } -- if (dev_priv->card_type < NV_50) { -- if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) -- aper_size = 64 * 1024 * 1024; -- else -- aper_size = 512 * 1024 * 1024; +- ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, +- NVOBJ_FLAG_ZERO_ALLOC | +- NVOBJ_FLAG_ZERO_FREE, &gpuobj); + if (dev_priv->card_type >= NV_50) { -+ ret = nouveau_vm_get(dev_priv->chan_vm, aper_size, -+ 12, NV_MEM_ACCESS_RW, -+ &dev_priv->gart_info.vma); -+ if (ret) -+ return ret; -+ -+ dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset; ++ dev_priv->gart_info.aper_base = 0; + dev_priv->gart_info.aper_size = aper_size; + dev_priv->gart_info.type = NOUVEAU_GART_HW; + dev_priv->gart_info.func = &nv50_sgdma_backend; @@ -1098,9 +2648,7 @@ index 9a250eb..a26383b 100644 + dev_priv->gart_info.func = &nv41_sgdma_backend; + align = 16; + } - -- obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; -- obj_size += 8; /* ctxdma header */ ++ + ret = nouveau_gpuobj_new(dev, NULL, aper_size / 1024, align, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &gpuobj); @@ -1108,10 +2656,7 @@ index 9a250eb..a26383b 100644 + NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); + return ret; + } - -- ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, -- NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &gpuobj); ++ + dev_priv->gart_info.sg_ctxdma = gpuobj; + dev_priv->gart_info.aper_base = 0; + dev_priv->gart_info.aper_size = aper_size; @@ -1123,7 +2668,7 @@ index 9a250eb..a26383b 100644 if (ret) { NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); return ret; -@@ -236,25 +489,14 @@ nouveau_sgdma_init(struct drm_device *dev) +@@ -236,25 +478,14 @@ nouveau_sgdma_init(struct drm_device *dev) (0 << 14) /* RW */ | (2 << 16) /* PCI */); nv_wo32(gpuobj, 4, aper_size - 1); @@ -1151,10 +2696,11 @@ index 9a250eb..a26383b 100644 return 0; } -@@ -265,6 +507,13 @@ nouveau_sgdma_takedown(struct drm_device *dev) +@@ -264,7 +495,13 @@ nouveau_sgdma_takedown(struct drm_device *dev) + struct drm_nouveau_private *dev_priv = dev->dev_private; nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); - nouveau_vm_put(&dev_priv->gart_info.vma); +- nouveau_vm_put(&dev_priv->gart_info.vma); + + if (dev_priv->gart_info.dummy.page) { + pci_unmap_page(dev->pdev, dev_priv->gart_info.dummy.addr, @@ -1166,10 +2712,89 @@ index 9a250eb..a26383b 100644 uint32_t diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index a54fc43..916505d 100644 +index a54fc43..eb4f09e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -929,12 +929,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) +@@ -376,15 +376,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->graph.destroy_context = nv50_graph_destroy_context; + engine->graph.load_context = nv50_graph_load_context; + engine->graph.unload_context = nv50_graph_unload_context; +- if (dev_priv->chipset != 0x86) ++ if (dev_priv->chipset == 0x50 || ++ dev_priv->chipset == 0xac) + engine->graph.tlb_flush = nv50_graph_tlb_flush; +- else { +- /* from what i can see nvidia do this on every +- * pre-NVA3 board except NVAC, but, we've only +- * ever seen problems on NV86 +- */ +- engine->graph.tlb_flush = nv86_graph_tlb_flush; +- } ++ else ++ engine->graph.tlb_flush = nv84_graph_tlb_flush; + engine->fifo.channels = 128; + engine->fifo.init = nv50_fifo_init; + engine->fifo.takedown = nv50_fifo_takedown; +@@ -544,7 +540,6 @@ static int + nouveau_card_init_channel(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_gpuobj *gpuobj = NULL; + int ret; + + ret = nouveau_channel_alloc(dev, &dev_priv->channel, +@@ -552,41 +547,8 @@ nouveau_card_init_channel(struct drm_device *dev) + if (ret) + return ret; + +- /* no dma objects on fermi... */ +- if (dev_priv->card_type >= NV_C0) +- goto out_done; +- +- ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, +- 0, dev_priv->vram_size, +- NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM, +- &gpuobj); +- if (ret) +- goto out_err; +- +- ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj); +- nouveau_gpuobj_ref(NULL, &gpuobj); +- if (ret) +- goto out_err; +- +- ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, +- 0, dev_priv->gart_info.aper_size, +- NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART, +- &gpuobj); +- if (ret) +- goto out_err; +- +- ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj); +- nouveau_gpuobj_ref(NULL, &gpuobj); +- if (ret) +- goto out_err; +- +-out_done: + mutex_unlock(&dev_priv->channel->mutex); + return 0; +- +-out_err: +- nouveau_channel_put(&dev_priv->channel); +- return ret; + } + + static void nouveau_switcheroo_set_state(struct pci_dev *pdev, +@@ -904,7 +866,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) + #ifdef CONFIG_X86 + primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; + #endif +- ++ + remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary); + return 0; + } +@@ -929,12 +891,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", dev->pci_vendor, dev->pci_device, dev->pdev->class); @@ -1182,7 +2807,7 @@ index a54fc43..916505d 100644 /* resource 0 is mmio regs */ /* resource 1 is linear FB */ /* resource 2 is RAMIN (mmio regs + 0x1000000) */ -@@ -947,7 +941,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) +@@ -947,7 +903,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) NV_ERROR(dev, "Unable to initialize the mmio mapping. " "Please report your setup to " DRIVER_EMAIL "\n"); ret = -EINVAL; @@ -1191,7 +2816,21 @@ index a54fc43..916505d 100644 } NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", (unsigned long long)mmio_start_offs); -@@ -1054,8 +1048,6 @@ err_ramin: +@@ -962,11 +918,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) + + /* Time to determine the card architecture */ + reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); ++ dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */ + + /* We're dealing with >=NV10 */ + if ((reg0 & 0x0f000000) > 0) { + /* Bit 27-20 contain the architecture in hex */ + dev_priv->chipset = (reg0 & 0xff00000) >> 20; ++ dev_priv->stepping = (reg0 & 0xff); + /* NV04 or NV05 */ + } else if ((reg0 & 0xff00fff0) == 0x20004000) { + if (reg0 & 0x00f00000) +@@ -1054,8 +1012,6 @@ err_ramin: iounmap(dev_priv->ramin); err_mmio: iounmap(dev_priv->mmio); @@ -1200,6 +2839,15 @@ index a54fc43..916505d 100644 err_priv: kfree(dev_priv); dev->dev_private = NULL; +@@ -1126,7 +1082,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, + getparam->value = 1; + break; + case NOUVEAU_GETPARAM_HAS_PAGEFLIP: +- getparam->value = (dev_priv->card_type < NV_50); ++ getparam->value = 1; + break; + case NOUVEAU_GETPARAM_GRAPH_UNITS: + /* NV40 and NV50 versions are quite different, but register diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 8d9968e..649b041 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c @@ -1276,10 +2924,74 @@ index d9ceaea..b97719f 100644 #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c -index 97d82ae..b4658f7 100644 +index 97d82ae..0059e6f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vm.c -@@ -311,18 +311,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, +@@ -28,7 +28,7 @@ + #include "nouveau_vm.h" + + void +-nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) ++nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) + { + struct nouveau_vm *vm = vma->vm; + struct nouveau_mm_node *r; +@@ -40,7 +40,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + +- list_for_each_entry(r, &vram->regions, rl_entry) { ++ delta = 0; ++ list_for_each_entry(r, &node->regions, rl_entry) { + u64 phys = (u64)r->offset << 12; + u32 num = r->length >> bits; + +@@ -52,7 +53,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) + end = max; + len = end - pte; + +- vm->map(vma, pgt, vram, pte, len, phys); ++ vm->map(vma, pgt, node, pte, len, phys, delta); + + num -= len; + pte += len; +@@ -60,6 +61,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) + pde++; + pte = 0; + } ++ ++ delta += (u64)len << vma->node->type; + } + } + +@@ -67,14 +70,14 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) + } + + void +-nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram) ++nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) + { +- nouveau_vm_map_at(vma, 0, vram); ++ nouveau_vm_map_at(vma, 0, node); + } + + void + nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, +- dma_addr_t *list) ++ struct nouveau_mem *mem, dma_addr_t *list) + { + struct nouveau_vm *vm = vma->vm; + int big = vma->node->type != vm->spg_shift; +@@ -94,7 +97,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, + end = max; + len = end - pte; + +- vm->map_sg(vma, pgt, pte, list, len); ++ vm->map_sg(vma, pgt, mem, pte, len, list); + + num -= len; + pte += len; +@@ -311,18 +314,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, vm->spg_shift = 12; vm->lpg_shift = 17; pgt_bits = 27; @@ -1299,6 +3011,106 @@ index 97d82ae..b4658f7 100644 } else { kfree(vm); return -ENOSYS; +diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h +index e119351..2e06b55 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_vm.h ++++ b/drivers/gpu/drm/nouveau/nouveau_vm.h +@@ -67,9 +67,10 @@ struct nouveau_vm { + void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); + void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, +- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); ++ struct nouveau_mem *, u32 pte, u32 cnt, ++ u64 phys, u64 delta); + void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, +- u32 pte, dma_addr_t *, u32 cnt); ++ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); + void (*flush)(struct nouveau_vm *); + }; +@@ -82,20 +83,20 @@ int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, + int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, + u32 access, struct nouveau_vma *); + void nouveau_vm_put(struct nouveau_vma *); +-void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *); +-void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *); ++void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); ++void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); + void nouveau_vm_unmap(struct nouveau_vma *); + void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); + void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, +- dma_addr_t *); ++ struct nouveau_mem *, dma_addr_t *); + + /* nv50_vm.c */ + void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); + void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, +- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); ++ struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); + void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, +- u32 pte, dma_addr_t *, u32 cnt); ++ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); + void nv50_vm_flush(struct nouveau_vm *); + void nv50_vm_flush_engine(struct drm_device *, int engine); +@@ -104,9 +105,9 @@ void nv50_vm_flush_engine(struct drm_device *, int engine); + void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + struct nouveau_gpuobj *pgt[2]); + void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, +- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); ++ struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); + void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, +- u32 pte, dma_addr_t *, u32 cnt); ++ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); + void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); + void nvc0_vm_flush(struct nouveau_vm *); + +diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c +index 04fdc00..75e87274 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_volt.c ++++ b/drivers/gpu/drm/nouveau/nouveau_volt.c +@@ -159,8 +159,16 @@ nouveau_volt_init(struct drm_device *dev) + headerlen = volt[1]; + recordlen = volt[2]; + entries = volt[3]; +- vidshift = hweight8(volt[5]); + vidmask = volt[4]; ++ /* no longer certain what volt[5] is, if it's related to ++ * the vid shift then it's definitely not a function of ++ * how many bits are set. ++ * ++ * after looking at a number of nva3+ vbios images, they ++ * all seem likely to have a static shift of 2.. lets ++ * go with that for now until proven otherwise. ++ */ ++ vidshift = 2; + break; + default: + NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); +diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c +index 297505e..5ffc5ba 100644 +--- a/drivers/gpu/drm/nouveau/nv04_crtc.c ++++ b/drivers/gpu/drm/nouveau/nv04_crtc.c +@@ -790,8 +790,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, + if (atomic) { + drm_fb = passed_fb; + fb = nouveau_framebuffer(passed_fb); +- } +- else { ++ } else { + /* If not atomic, we can go ahead and pin, and unpin the + * old fb we were passed. + */ +@@ -1031,7 +1030,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + + ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); ++ 0, 0x0000, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index c82db37..12098bf 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -1376,6 +3188,53 @@ index f89d104..db465a3 100644 status &= ~0x00000010; nv_wr32(dev, 0x002100, 0x00000010); } +diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c +index af75015..055677a 100644 +--- a/drivers/gpu/drm/nouveau/nv04_graph.c ++++ b/drivers/gpu/drm/nouveau/nv04_graph.c +@@ -507,7 +507,7 @@ int nv04_graph_init(struct drm_device *dev) + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ + nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000); + /*1231C000 blob, 001 haiku*/ +- //*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ ++ /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ + nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100); + /*0x72111100 blob , 01 haiku*/ + /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ +@@ -1232,8 +1232,7 @@ static struct nouveau_bitfield nv04_graph_intr[] = { + {} + }; + +-static struct nouveau_bitfield nv04_graph_nstatus[] = +-{ ++static struct nouveau_bitfield nv04_graph_nstatus[] = { + { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, +@@ -1241,8 +1240,7 @@ static struct nouveau_bitfield nv04_graph_nstatus[] = + {} + }; + +-struct nouveau_bitfield nv04_graph_nsource[] = +-{ ++struct nouveau_bitfield nv04_graph_nsource[] = { + { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, + { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, +diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c +index 8c92edb..531d7ba 100644 +--- a/drivers/gpu/drm/nouveau/nv10_graph.c ++++ b/drivers/gpu/drm/nouveau/nv10_graph.c +@@ -1117,8 +1117,7 @@ struct nouveau_bitfield nv10_graph_intr[] = { + {} + }; + +-struct nouveau_bitfield nv10_graph_nstatus[] = +-{ ++struct nouveau_bitfield nv10_graph_nstatus[] = { + { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c index f3d9c05..f0ac2a7 100644 --- a/drivers/gpu/drm/nouveau/nv40_fb.c @@ -1453,15 +3312,476 @@ index f3d9c05..f0ac2a7 100644 switch (dev_priv->chipset) { case 0x40: +diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c +index 9023c4d..e900a51 100644 +--- a/drivers/gpu/drm/nouveau/nv50_crtc.c ++++ b/drivers/gpu/drm/nouveau/nv50_crtc.c +@@ -65,7 +65,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) + { + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int index = nv_crtc->index, ret; + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); +@@ -135,8 +135,7 @@ static int + nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) + { + struct drm_device *dev = nv_crtc->base.dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + NV_DEBUG_KMS(dev, "\n"); +@@ -186,8 +185,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) + struct nouveau_connector *nv_connector = + nouveau_crtc_connector_get(nv_crtc); + struct drm_device *dev = nv_crtc->base.dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct drm_display_mode *native_mode = NULL; + struct drm_display_mode *mode = &nv_crtc->base.mode; + uint32_t outX, outY, horiz, vert; +@@ -445,6 +443,39 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) + { + } + ++static int ++nv50_crtc_wait_complete(struct drm_crtc *crtc) ++{ ++ struct drm_device *dev = crtc->dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; ++ struct nv50_display *disp = nv50_display(dev); ++ struct nouveau_channel *evo = disp->master; ++ u64 start; ++ int ret; ++ ++ ret = RING_SPACE(evo, 6); ++ if (ret) ++ return ret; ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x80000000); ++ BEGIN_RING(evo, 0, 0x0080, 1); ++ OUT_RING (evo, 0); ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x00000000); ++ ++ nv_wo32(disp->ntfy, 0x000, 0x00000000); ++ FIRE_RING (evo); ++ ++ start = ptimer->read(dev); ++ do { ++ if (nv_ro32(disp->ntfy, 0x000)) ++ return 0; ++ } while (ptimer->read(dev) - start < 2000000000ULL); ++ ++ return -EBUSY; ++} ++ + static void + nv50_crtc_prepare(struct drm_crtc *crtc) + { +@@ -453,6 +484,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc) + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + ++ nv50_display_flip_stop(crtc); + drm_vblank_pre_modeset(dev, nv_crtc->index); + nv50_crtc_blank(nv_crtc, true); + } +@@ -461,24 +493,14 @@ static void + nv50_crtc_commit(struct drm_crtc *crtc) + { + struct drm_device *dev = crtc->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); +- int ret; + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + + nv50_crtc_blank(nv_crtc, false); + drm_vblank_post_modeset(dev, nv_crtc->index); +- +- ret = RING_SPACE(evo, 2); +- if (ret) { +- NV_ERROR(dev, "no space while committing crtc\n"); +- return; +- } +- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING (evo, 0); +- FIRE_RING (evo); ++ nv50_crtc_wait_complete(crtc); ++ nv50_display_flip_next(crtc, crtc->fb, NULL); + } + + static bool +@@ -491,15 +513,15 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, + static int + nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *passed_fb, +- int x, int y, bool update, bool atomic) ++ int x, int y, bool atomic) + { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct drm_device *dev = nv_crtc->base.dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct drm_framebuffer *drm_fb = nv_crtc->base.fb; + struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); +- int ret, format; ++ int ret; + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + +@@ -510,8 +532,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + if (atomic) { + drm_fb = passed_fb; + fb = nouveau_framebuffer(passed_fb); +- } +- else { ++ } else { + /* If not atomic, we can go ahead and pin, and unpin the + * old fb we were passed. + */ +@@ -525,28 +546,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + } + } + +- switch (drm_fb->depth) { +- case 8: +- format = NV50_EVO_CRTC_FB_DEPTH_8; +- break; +- case 15: +- format = NV50_EVO_CRTC_FB_DEPTH_15; +- break; +- case 16: +- format = NV50_EVO_CRTC_FB_DEPTH_16; +- break; +- case 24: +- case 32: +- format = NV50_EVO_CRTC_FB_DEPTH_24; +- break; +- case 30: +- format = NV50_EVO_CRTC_FB_DEPTH_30; +- break; +- default: +- NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth); +- return -EINVAL; +- } +- + nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; + nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); + nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; +@@ -556,14 +555,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); +- if (nv_crtc->fb.tile_flags == 0x7a00 || +- nv_crtc->fb.tile_flags == 0xfe00) +- OUT_RING(evo, NvEvoFB32); +- else +- if (nv_crtc->fb.tile_flags == 0x7000) +- OUT_RING(evo, NvEvoFB16); +- else +- OUT_RING(evo, NvEvoVRAM_LP); ++ OUT_RING (evo, fb->r_dma); + } + + ret = RING_SPACE(evo, 12); +@@ -571,45 +563,26 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5); +- OUT_RING(evo, nv_crtc->fb.offset >> 8); +- OUT_RING(evo, 0); +- OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width); +- if (!nv_crtc->fb.tile_flags) { +- OUT_RING(evo, drm_fb->pitch | (1 << 20)); +- } else { +- u32 tile_mode = fb->nvbo->tile_mode; +- if (dev_priv->card_type >= NV_C0) +- tile_mode >>= 4; +- OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode); +- } +- if (dev_priv->chipset == 0x50) +- OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); +- else +- OUT_RING(evo, format); ++ OUT_RING (evo, nv_crtc->fb.offset >> 8); ++ OUT_RING (evo, 0); ++ OUT_RING (evo, (drm_fb->height << 16) | drm_fb->width); ++ OUT_RING (evo, fb->r_pitch); ++ OUT_RING (evo, fb->r_format); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1); +- OUT_RING(evo, fb->base.depth == 8 ? +- NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); ++ OUT_RING (evo, fb->base.depth == 8 ? ++ NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); +- OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); ++ OUT_RING (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); +- OUT_RING(evo, (y << 16) | x); ++ OUT_RING (evo, (y << 16) | x); + + if (nv_crtc->lut.depth != fb->base.depth) { + nv_crtc->lut.depth = fb->base.depth; + nv50_crtc_lut_load(crtc); + } + +- if (update) { +- ret = RING_SPACE(evo, 2); +- if (ret) +- return ret; +- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING(evo, 0); +- FIRE_RING(evo); +- } +- + return 0; + } + +@@ -619,8 +592,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_framebuffer *old_fb) + { + struct drm_device *dev = crtc->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + struct nouveau_connector *nv_connector = NULL; + uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; +@@ -700,14 +672,25 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); + nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); + +- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false); ++ return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); + } + + static int + nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) + { +- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false); ++ int ret; ++ ++ nv50_display_flip_stop(crtc); ++ ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); ++ if (ret) ++ return ret; ++ ++ ret = nv50_crtc_wait_complete(crtc); ++ if (ret) ++ return ret; ++ ++ return nv50_display_flip_next(crtc, crtc->fb, NULL); + } + + static int +@@ -715,7 +698,14 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, enum mode_set_atomic state) + { +- return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); ++ int ret; ++ ++ nv50_display_flip_stop(crtc); ++ ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true); ++ if (ret) ++ return ret; ++ ++ return nv50_crtc_wait_complete(crtc); + } + + static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { +@@ -758,7 +748,7 @@ nv50_crtc_create(struct drm_device *dev, int index) + nv_crtc->lut.depth = 0; + + ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nv_crtc->lut.nvbo); ++ 0, 0x0000, &nv_crtc->lut.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) +@@ -784,7 +774,7 @@ nv50_crtc_create(struct drm_device *dev, int index) + drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); + + ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, +- 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); ++ 0, 0x0000, &nv_crtc->cursor.nvbo); + if (!ret) { + ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); + if (!ret) +diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c +index 1b9ce30..9752c35 100644 +--- a/drivers/gpu/drm/nouveau/nv50_cursor.c ++++ b/drivers/gpu/drm/nouveau/nv50_cursor.c +@@ -36,9 +36,9 @@ + static void + nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) + { +- struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; + struct drm_device *dev = nv_crtc->base.dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + NV_DEBUG_KMS(dev, "\n"); +@@ -71,9 +71,9 @@ nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) + static void + nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) + { +- struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; + struct drm_device *dev = nv_crtc->base.dev; ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + NV_DEBUG_KMS(dev, "\n"); +diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c +index 875414b..808f3ec 100644 +--- a/drivers/gpu/drm/nouveau/nv50_dac.c ++++ b/drivers/gpu/drm/nouveau/nv50_dac.c +@@ -41,8 +41,7 @@ nv50_dac_disconnect(struct drm_encoder *encoder) + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + if (!nv_encoder->crtc) +@@ -216,8 +215,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); + uint32_t mode_ctl = 0, mode_ctl2 = 0; + int ret; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c -index 7cc94ed..a804a35 100644 +index 7cc94ed..75a376c 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c -@@ -345,12 +345,15 @@ int nv50_display_create(struct drm_device *dev) +@@ -24,6 +24,7 @@ + * + */ + ++#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) + #include "nv50_display.h" + #include "nouveau_crtc.h" + #include "nouveau_encoder.h" +@@ -34,6 +35,7 @@ + #include "drm_crtc_helper.h" + + static void nv50_display_isr(struct drm_device *); ++static void nv50_display_bh(unsigned long); + + static inline int + nv50_sor_nr(struct drm_device *dev) +@@ -172,16 +174,16 @@ nv50_display_init(struct drm_device *dev) + ret = nv50_evo_init(dev); + if (ret) + return ret; +- evo = dev_priv->evo; ++ evo = nv50_display(dev)->master; + + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); + +- ret = RING_SPACE(evo, 11); ++ ret = RING_SPACE(evo, 15); + if (ret) + return ret; + BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); + OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); +- OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE); ++ OUT_RING(evo, NvEvoSync); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); + OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); +@@ -190,6 +192,11 @@ nv50_display_init(struct drm_device *dev) + OUT_RING(evo, 0); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); + OUT_RING(evo, 0); ++ /* required to make display sync channels not hate life */ ++ BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1); ++ OUT_RING (evo, 0x00000311); ++ BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1); ++ OUT_RING (evo, 0x00000311); + FIRE_RING(evo); + if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) + NV_ERROR(dev, "evo pushbuf stalled\n"); +@@ -201,6 +208,8 @@ nv50_display_init(struct drm_device *dev) + static int nv50_display_disable(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); ++ struct nouveau_channel *evo = disp->master; + struct drm_crtc *drm_crtc; + int ret, i; + +@@ -212,12 +221,12 @@ static int nv50_display_disable(struct drm_device *dev) + nv50_crtc_blank(crtc, true); + } + +- ret = RING_SPACE(dev_priv->evo, 2); ++ ret = RING_SPACE(evo, 2); + if (ret == 0) { +- BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1); +- OUT_RING(dev_priv->evo, 0); ++ BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); ++ OUT_RING(evo, 0); + } +- FIRE_RING(dev_priv->evo); ++ FIRE_RING(evo); + + /* Almost like ack'ing a vblank interrupt, maybe in the spirit of + * cleaning up? +@@ -267,10 +276,16 @@ int nv50_display_create(struct drm_device *dev) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_table *dcb = &dev_priv->vbios.dcb; + struct drm_connector *connector, *ct; ++ struct nv50_display *priv; + int ret, i; + + NV_DEBUG_KMS(dev, "\n"); + ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ dev_priv->engine.display.priv = priv; ++ + /* init basic kernel modesetting */ + drm_mode_config_init(dev); + +@@ -330,7 +345,7 @@ int nv50_display_create(struct drm_device *dev) + } + } + +- INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); ++ tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); + nouveau_irq_register(dev, 26, nv50_display_isr); + + ret = nv50_display_init(dev); +@@ -345,12 +360,131 @@ int nv50_display_create(struct drm_device *dev) void nv50_display_destroy(struct drm_device *dev) { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + NV_DEBUG_KMS(dev, "\n"); @@ -1469,33 +3789,443 @@ index 7cc94ed..a804a35 100644 nv50_display_disable(dev); nouveau_irq_unregister(dev, 26); -+ flush_work_sync(&dev_priv->irq_work); ++ kfree(disp); ++} ++ ++void ++nv50_display_flip_stop(struct drm_crtc *crtc) ++{ ++ struct nv50_display *disp = nv50_display(crtc->dev); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; ++ struct nouveau_channel *evo = dispc->sync; ++ int ret; ++ ++ ret = RING_SPACE(evo, 8); ++ if (ret) { ++ WARN_ON(1); ++ return; ++ } ++ ++ BEGIN_RING(evo, 0, 0x0084, 1); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x0094, 1); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x00c0, 1); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x0080, 1); ++ OUT_RING (evo, 0x00000000); ++ FIRE_RING (evo); ++} ++ ++int ++nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ++ struct nouveau_channel *chan) ++{ ++ struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; ++ struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); ++ struct nv50_display *disp = nv50_display(crtc->dev); ++ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); ++ struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; ++ struct nouveau_channel *evo = dispc->sync; ++ int ret; ++ ++ ret = RING_SPACE(evo, 24); ++ if (unlikely(ret)) ++ return ret; ++ ++ /* synchronise with the rendering channel, if necessary */ ++ if (likely(chan)) { ++ u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset; ++ ++ ret = RING_SPACE(chan, 10); ++ if (ret) { ++ WIND_RING(evo); ++ return ret; ++ } ++ ++ if (dev_priv->chipset < 0xc0) { ++ BEGIN_RING(chan, NvSubSw, 0x0060, 2); ++ OUT_RING (chan, NvEvoSema0 + nv_crtc->index); ++ OUT_RING (chan, dispc->sem.offset); ++ BEGIN_RING(chan, NvSubSw, 0x006c, 1); ++ OUT_RING (chan, 0xf00d0000 | dispc->sem.value); ++ BEGIN_RING(chan, NvSubSw, 0x0064, 2); ++ OUT_RING (chan, dispc->sem.offset ^ 0x10); ++ OUT_RING (chan, 0x74b1e000); ++ BEGIN_RING(chan, NvSubSw, 0x0060, 1); ++ if (dev_priv->chipset < 0x84) ++ OUT_RING (chan, NvSema); ++ else ++ OUT_RING (chan, chan->vram_handle); ++ } else { ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset)); ++ OUT_RING (chan, 0xf00d0000 | dispc->sem.value); ++ OUT_RING (chan, 0x1002); ++ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); ++ OUT_RING (chan, upper_32_bits(offset)); ++ OUT_RING (chan, lower_32_bits(offset ^ 0x10)); ++ OUT_RING (chan, 0x74b1e000); ++ OUT_RING (chan, 0x1001); ++ } ++ FIRE_RING (chan); ++ } else { ++ nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4, ++ 0xf00d0000 | dispc->sem.value); ++ } ++ ++ /* queue the flip on the crtc's "display sync" channel */ ++ BEGIN_RING(evo, 0, 0x0100, 1); ++ OUT_RING (evo, 0xfffe0000); ++ BEGIN_RING(evo, 0, 0x0084, 5); ++ OUT_RING (evo, chan ? 0x00000100 : 0x00000010); ++ OUT_RING (evo, dispc->sem.offset); ++ OUT_RING (evo, 0xf00d0000 | dispc->sem.value); ++ OUT_RING (evo, 0x74b1e000); ++ OUT_RING (evo, NvEvoSync); ++ BEGIN_RING(evo, 0, 0x00a0, 2); ++ OUT_RING (evo, 0x00000000); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x00c0, 1); ++ OUT_RING (evo, nv_fb->r_dma); ++ BEGIN_RING(evo, 0, 0x0110, 2); ++ OUT_RING (evo, 0x00000000); ++ OUT_RING (evo, 0x00000000); ++ BEGIN_RING(evo, 0, 0x0800, 5); ++ OUT_RING (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8); ++ OUT_RING (evo, 0); ++ OUT_RING (evo, (fb->height << 16) | fb->width); ++ OUT_RING (evo, nv_fb->r_pitch); ++ OUT_RING (evo, nv_fb->r_format); ++ BEGIN_RING(evo, 0, 0x0080, 1); ++ OUT_RING (evo, 0x00000000); ++ FIRE_RING (evo); ++ ++ dispc->sem.offset ^= 0x10; ++ dispc->sem.value++; ++ return 0; } static u16 -@@ -587,7 +590,7 @@ static void +@@ -466,11 +600,12 @@ static void + nv50_display_unk10_handler(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + u32 unk30 = nv_rd32(dev, 0x610030), mc; + int i, crtc, or, type = OUTPUT_ANY; + + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); +- dev_priv->evo_irq.dcb = NULL; ++ disp->irq.dcb = NULL; + + nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); + +@@ -541,7 +676,7 @@ nv50_display_unk10_handler(struct drm_device *dev) + + if (dcb->type == type && (dcb->or & (1 << or))) { + nouveau_bios_run_display_table(dev, dcb, 0, -1); +- dev_priv->evo_irq.dcb = dcb; ++ disp->irq.dcb = dcb; + goto ack; + } + } +@@ -587,15 +722,16 @@ static void nv50_display_unk20_handler(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc; ++ struct nv50_display *disp = nv50_display(dev); + u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; struct dcb_entry *dcb; int i, crtc, or, type = OUTPUT_ANY; -@@ -836,7 +839,7 @@ nv50_display_isr(struct drm_device *dev) + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); +- dcb = dev_priv->evo_irq.dcb; ++ dcb = disp->irq.dcb; + if (dcb) { + nouveau_bios_run_display_table(dev, dcb, 0, -2); +- dev_priv->evo_irq.dcb = NULL; ++ disp->irq.dcb = NULL; + } + + /* CRTC clock change requested? */ +@@ -692,9 +828,9 @@ nv50_display_unk20_handler(struct drm_device *dev) + nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); + } + +- dev_priv->evo_irq.dcb = dcb; +- dev_priv->evo_irq.pclk = pclk; +- dev_priv->evo_irq.script = script; ++ disp->irq.dcb = dcb; ++ disp->irq.pclk = pclk; ++ disp->irq.script = script; + + ack: + nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); +@@ -735,13 +871,13 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) + static void + nv50_display_unk40_handler(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct dcb_entry *dcb = dev_priv->evo_irq.dcb; +- u16 script = dev_priv->evo_irq.script; +- u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk; ++ struct nv50_display *disp = nv50_display(dev); ++ struct dcb_entry *dcb = disp->irq.dcb; ++ u16 script = disp->irq.script; ++ u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk; + + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); +- dev_priv->evo_irq.dcb = NULL; ++ disp->irq.dcb = NULL; + if (!dcb) + goto ack; + +@@ -754,12 +890,10 @@ ack: + nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); + } + +-void +-nv50_display_irq_handler_bh(struct work_struct *work) ++static void ++nv50_display_bh(unsigned long data) + { +- struct drm_nouveau_private *dev_priv = +- container_of(work, struct drm_nouveau_private, irq_work); +- struct drm_device *dev = dev_priv->dev; ++ struct drm_device *dev = (struct drm_device *)data; + + for (;;) { + uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); +@@ -807,7 +941,7 @@ nv50_display_error_handler(struct drm_device *dev) + static void + nv50_display_isr(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + uint32_t delayed = 0; + + while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { +@@ -835,8 +969,7 @@ nv50_display_isr(struct drm_device *dev) + NV50_PDISPLAY_INTR_1_CLK_UNK40)); if (clock) { nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); - if (!work_pending(&dev_priv->irq_work)) +- if (!work_pending(&dev_priv->irq_work)) - queue_work(dev_priv->wq, &dev_priv->irq_work); -+ schedule_work(&dev_priv->irq_work); ++ tasklet_schedule(&disp->tasklet); delayed |= clock; intr1 &= ~clock; } +diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h +index f0e30b78..c2da503 100644 +--- a/drivers/gpu/drm/nouveau/nv50_display.h ++++ b/drivers/gpu/drm/nouveau/nv50_display.h +@@ -35,7 +35,36 @@ + #include "nouveau_crtc.h" + #include "nv50_evo.h" + +-void nv50_display_irq_handler_bh(struct work_struct *work); ++struct nv50_display_crtc { ++ struct nouveau_channel *sync; ++ struct { ++ struct nouveau_bo *bo; ++ u32 offset; ++ u16 value; ++ } sem; ++}; ++ ++struct nv50_display { ++ struct nouveau_channel *master; ++ struct nouveau_gpuobj *ntfy; ++ ++ struct nv50_display_crtc crtc[2]; ++ ++ struct tasklet_struct tasklet; ++ struct { ++ struct dcb_entry *dcb; ++ u16 script; ++ u32 pclk; ++ } irq; ++}; ++ ++static inline struct nv50_display * ++nv50_display(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ return dev_priv->engine.display.priv; ++} ++ + int nv50_display_early_init(struct drm_device *dev); + void nv50_display_late_takedown(struct drm_device *dev); + int nv50_display_create(struct drm_device *dev); +@@ -44,4 +73,15 @@ void nv50_display_destroy(struct drm_device *dev); + int nv50_crtc_blank(struct nouveau_crtc *, bool blank); + int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); + ++int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, ++ struct nouveau_channel *chan); ++void nv50_display_flip_stop(struct drm_crtc *); ++ ++int nv50_evo_init(struct drm_device *dev); ++void nv50_evo_fini(struct drm_device *dev); ++void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, ++ u64 size); ++int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, ++ u64 base, u64 size, struct nouveau_gpuobj **); ++ + #endif /* __NV50_DISPLAY_H__ */ diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c -index 0ea090f..3055dbe 100644 +index 0ea090f..c8e83c1 100644 --- a/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/drivers/gpu/drm/nouveau/nv50_evo.c -@@ -182,6 +182,7 @@ nv50_evo_channel_init(struct nouveau_channel *evo) +@@ -27,20 +27,17 @@ + #include "nouveau_drv.h" + #include "nouveau_dma.h" + #include "nouveau_ramht.h" ++#include "nv50_display.h" + + static void + nv50_evo_channel_del(struct nouveau_channel **pevo) + { +- struct drm_nouveau_private *dev_priv; + struct nouveau_channel *evo = *pevo; + + if (!evo) + return; + *pevo = NULL; + +- dev_priv = evo->dev->dev_private; +- dev_priv->evo_alloc &= ~(1 << evo->id); +- + nouveau_gpuobj_channel_takedown(evo); + nouveau_bo_unmap(evo->pushbuf_bo); + nouveau_bo_ref(NULL, &evo->pushbuf_bo); +@@ -51,42 +48,61 @@ nv50_evo_channel_del(struct nouveau_channel **pevo) + kfree(evo); + } + ++void ++nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size) ++{ ++ struct drm_nouveau_private *dev_priv = obj->dev->dev_private; ++ u32 flags5; ++ ++ if (dev_priv->chipset < 0xc0) { ++ /* not supported on 0x50, specified in format mthd */ ++ if (dev_priv->chipset == 0x50) ++ memtype = 0; ++ flags5 = 0x00010000; ++ } else { ++ if (memtype & 0x80000000) ++ flags5 = 0x00000000; /* large pages */ ++ else ++ flags5 = 0x00020000; ++ } ++ ++ nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM, ++ NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0); ++ nv_wo32(obj, 0x14, flags5); ++ dev_priv->engine.instmem.flush(obj->dev); ++} ++ + int +-nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, +- u32 tile_flags, u32 magic_flags, u32 offset, u32 limit, +- u32 flags5) ++nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, ++ u64 base, u64 size, struct nouveau_gpuobj **pobj) + { +- struct drm_nouveau_private *dev_priv = evo->dev->dev_private; +- struct drm_device *dev = evo->dev; ++ struct nv50_display *disp = nv50_display(evo->dev); + struct nouveau_gpuobj *obj = NULL; + int ret; + +- ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); ++ ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj); + if (ret) + return ret; + obj->engine = NVOBJ_ENGINE_DISPLAY; + +- nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); +- nv_wo32(obj, 4, limit); +- nv_wo32(obj, 8, offset); +- nv_wo32(obj, 12, 0x00000000); +- nv_wo32(obj, 16, 0x00000000); +- nv_wo32(obj, 20, flags5); +- dev_priv->engine.instmem.flush(dev); ++ nv50_evo_dmaobj_init(obj, memtype, base, size); + +- ret = nouveau_ramht_insert(evo, name, obj); +- nouveau_gpuobj_ref(NULL, &obj); +- if (ret) { +- return ret; +- } ++ ret = nouveau_ramht_insert(evo, handle, obj); ++ if (ret) ++ goto out; + +- return 0; ++ if (pobj) ++ nouveau_gpuobj_ref(obj, pobj); ++out: ++ nouveau_gpuobj_ref(NULL, &obj); ++ return ret; + } + + static int +-nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) ++nv50_evo_channel_new(struct drm_device *dev, int chid, ++ struct nouveau_channel **pevo) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + struct nouveau_channel *evo; + int ret; + +@@ -95,25 +111,13 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) + return -ENOMEM; + *pevo = evo; + +- for (evo->id = 0; evo->id < 5; evo->id++) { +- if (dev_priv->evo_alloc & (1 << evo->id)) +- continue; +- +- dev_priv->evo_alloc |= (1 << evo->id); +- break; +- } +- +- if (evo->id == 5) { +- kfree(evo); +- return -ENODEV; +- } +- ++ evo->id = chid; + evo->dev = dev; + evo->user_get = 4; + evo->user_put = 0; + + ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, +- false, true, &evo->pushbuf_bo); ++ &evo->pushbuf_bo); + if (ret == 0) + ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); + if (ret) { +@@ -138,8 +142,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) + } + + /* bind primary evo channel's ramht to the channel */ +- if (dev_priv->evo && evo != dev_priv->evo) +- nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); ++ if (disp->master && evo != disp->master) ++ nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL); + + return 0; + } +@@ -182,6 +186,7 @@ nv50_evo_channel_init(struct nouveau_channel *evo) nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); evo->dma.max = (4096/4) - 2; @@ -1503,14 +4233,386 @@ index 0ea090f..3055dbe 100644 evo->dma.put = 0; evo->dma.cur = evo->dma.put; evo->dma.free = evo->dma.max - evo->dma.cur; -diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c -index 50290de..efc8cd4 100644 ---- a/drivers/gpu/drm/nouveau/nv50_fb.c -+++ b/drivers/gpu/drm/nouveau/nv50_fb.c -@@ -95,12 +95,109 @@ nv50_fb_takedown(struct drm_device *dev) - kfree(priv); +@@ -212,21 +217,39 @@ nv50_evo_channel_fini(struct nouveau_channel *evo) + } } ++static void ++nv50_evo_destroy(struct drm_device *dev) ++{ ++ struct nv50_display *disp = nv50_display(dev); ++ int i; ++ ++ for (i = 0; i < 2; i++) { ++ if (disp->crtc[i].sem.bo) { ++ nouveau_bo_unmap(disp->crtc[i].sem.bo); ++ nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo); ++ } ++ nv50_evo_channel_del(&disp->crtc[i].sync); ++ } ++ nouveau_gpuobj_ref(NULL, &disp->ntfy); ++ nv50_evo_channel_del(&disp->master); ++} ++ + static int + nv50_evo_create(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); + struct nouveau_gpuobj *ramht = NULL; + struct nouveau_channel *evo; +- int ret; ++ int ret, i, j; + + /* create primary evo channel, the one we use for modesetting + * purporses + */ +- ret = nv50_evo_channel_new(dev, &dev_priv->evo); ++ ret = nv50_evo_channel_new(dev, 0, &disp->master); + if (ret) + return ret; +- evo = dev_priv->evo; ++ evo = disp->master; + + /* setup object management on it, any other evo channel will + * use this also as there's no per-channel support on the +@@ -236,109 +259,167 @@ nv50_evo_create(struct drm_device *dev) + NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); + if (ret) { + NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ goto err; + } + + ret = drm_mm_init(&evo->ramin_heap, 0, 32768); + if (ret) { + NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ goto err; + } + + ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); + if (ret) { + NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ goto err; + } + + ret = nouveau_ramht_new(dev, ramht, &evo->ramht); + nouveau_gpuobj_ref(NULL, &ramht); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ if (ret) ++ goto err; ++ ++ /* not sure exactly what this is.. ++ * ++ * the first dword of the structure is used by nvidia to wait on ++ * full completion of an EVO "update" command. ++ * ++ * method 0x8c on the master evo channel will fill a lot more of ++ * this structure with some undefined info ++ */ ++ ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0, ++ NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000, ++ disp->ntfy->vinst, disp->ntfy->size, NULL); ++ if (ret) ++ goto err; + + /* create some default objects for the scanout memtypes we support */ +- if (dev_priv->card_type >= NV_C0) { +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19, +- 0, 0xffffffff, 0x00000000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, +- 0, dev_priv->vram_size, 0x00020000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, +- 0, dev_priv->vram_size, 0x00000000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } +- } else { +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, +- 0, 0xffffffff, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + ++ ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, +- 0, 0xffffffff, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ /* create "display sync" channels and other structures we need ++ * to implement page flipping ++ */ ++ for (i = 0; i < 2; i++) { ++ struct nv50_display_crtc *dispc = &disp->crtc[i]; ++ u64 offset; + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, +- 0, dev_priv->vram_size, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; ++ ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync); ++ if (ret) ++ goto err; ++ ++ ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM, ++ 0, 0x0000, &dispc->sem.bo); ++ if (!ret) { ++ offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; ++ ++ ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); ++ if (!ret) ++ ret = nouveau_bo_map(dispc->sem.bo); ++ if (ret) ++ nouveau_bo_ref(NULL, &dispc->sem.bo); + } + +- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, +- 0, dev_priv->vram_size, 0x00010000); +- if (ret) { +- nv50_evo_channel_del(&dev_priv->evo); +- return ret; +- } ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000, ++ offset, 4096, NULL); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? ++ 0x7a00 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; ++ ++ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | ++ (dev_priv->chipset < 0xc0 ? ++ 0x7000 : 0xfe00), ++ 0, dev_priv->vram_size, NULL); ++ if (ret) ++ goto err; ++ ++ for (j = 0; j < 4096; j += 4) ++ nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000); ++ dispc->sem.offset = 0; + } + + return 0; ++ ++err: ++ nv50_evo_destroy(dev); ++ return ret; + } + + int + nv50_evo_init(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- int ret; ++ struct nv50_display *disp = nv50_display(dev); ++ int ret, i; + +- if (!dev_priv->evo) { ++ if (!disp->master) { + ret = nv50_evo_create(dev); + if (ret) + return ret; + } + +- return nv50_evo_channel_init(dev_priv->evo); ++ ret = nv50_evo_channel_init(disp->master); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < 2; i++) { ++ ret = nv50_evo_channel_init(disp->crtc[i].sync); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; + } + + void + nv50_evo_fini(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nv50_display *disp = nv50_display(dev); ++ int i; + +- if (dev_priv->evo) { +- nv50_evo_channel_fini(dev_priv->evo); +- nv50_evo_channel_del(&dev_priv->evo); ++ for (i = 0; i < 2; i++) { ++ if (disp->crtc[i].sync) ++ nv50_evo_channel_fini(disp->crtc[i].sync); + } ++ ++ if (disp->master) ++ nv50_evo_channel_fini(disp->master); ++ ++ nv50_evo_destroy(dev); + } +diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h +index aa4f0d3..3860ca6 100644 +--- a/drivers/gpu/drm/nouveau/nv50_evo.h ++++ b/drivers/gpu/drm/nouveau/nv50_evo.h +@@ -27,12 +27,6 @@ + #ifndef __NV50_EVO_H__ + #define __NV50_EVO_H__ + +-int nv50_evo_init(struct drm_device *dev); +-void nv50_evo_fini(struct drm_device *dev); +-int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, +- u32 tile_flags, u32 magic_flags, +- u32 offset, u32 limit); +- + #define NV50_EVO_UPDATE 0x00000080 + #define NV50_EVO_UNK84 0x00000084 + #define NV50_EVO_UNK84_NOTIFY 0x40000000 +@@ -119,5 +113,7 @@ int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, + /* Both of these are needed, otherwise nothing happens. */ + #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 + #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc ++#define NV50_EVO_CRTC_UNK900 0x00000900 ++#define NV50_EVO_CRTC_UNK904 0x00000904 + + #endif +diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c +index 50290de..ddebd71 100644 +--- a/drivers/gpu/drm/nouveau/nv50_fb.c ++++ b/drivers/gpu/drm/nouveau/nv50_fb.c +@@ -8,31 +8,61 @@ struct nv50_fb_priv { + dma_addr_t r100c08; + }; + ++static void ++nv50_fb_destroy(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ struct nv50_fb_priv *priv = pfb->priv; ++ ++ if (pfb->tag_heap.free_stack.next) ++ drm_mm_takedown(&pfb->tag_heap); ++ ++ if (priv->r100c08_page) { ++ pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, ++ PCI_DMA_BIDIRECTIONAL); ++ __free_page(priv->r100c08_page); ++ } ++ ++ kfree(priv); ++ pfb->priv = NULL; ++} ++ + static int + nv50_fb_create(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nv50_fb_priv *priv; ++ u32 tagmem; ++ int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; ++ pfb->priv = priv; + + priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c08_page) { +- kfree(priv); ++ nv50_fb_destroy(dev); + return -ENOMEM; + } + + priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { +- __free_page(priv->r100c08_page); +- kfree(priv); ++ nv50_fb_destroy(dev); + return -EFAULT; + } + +- dev_priv->engine.fb.priv = priv; ++ tagmem = nv_rd32(dev, 0x100320); ++ NV_DEBUG(dev, "%d tags available\n", tagmem); ++ ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); ++ if (ret) { ++ nv50_fb_destroy(dev); ++ return ret; ++ } ++ + return 0; + } + +@@ -81,26 +111,112 @@ nv50_fb_init(struct drm_device *dev) + void + nv50_fb_takedown(struct drm_device *dev) + { +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nv50_fb_priv *priv; ++ nv50_fb_destroy(dev); ++} + +- priv = dev_priv->engine.fb.priv; +- if (!priv) +- return; +- dev_priv->engine.fb.priv = NULL; +static struct nouveau_enum vm_dispatch_subclients[] = { + { 0x00000000, "GRCTX", NULL }, + { 0x00000001, "NOTIFY", NULL }, @@ -1521,7 +4623,12 @@ index 50290de..efc8cd4 100644 + { 0x00000006, "M2M_NOTIFY", NULL }, + {} +}; -+ + +- pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, +- PCI_DMA_BIDIRECTIONAL); +- __free_page(priv->r100c08_page); +- kfree(priv); +-} +static struct nouveau_enum vm_ccache_subclients[] = { + { 0x00000000, "CB", NULL }, + { 0x00000001, "TIC", NULL }, @@ -1605,7 +4712,7 @@ index 50290de..efc8cd4 100644 + { 0x0000000f, "DMAOBJ_LIMIT", NULL }, + {} +}; -+ + void -nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) +nv50_fb_vm_trap(struct drm_device *dev, int display) @@ -1618,7 +4725,7 @@ index 50290de..efc8cd4 100644 int i, ch; idx = nv_rd32(dev, 0x100c90); -@@ -117,8 +214,8 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) +@@ -117,8 +233,8 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) if (!display) return; @@ -1628,7 +4735,7 @@ index 50290de..efc8cd4 100644 spin_lock_irqsave(&dev_priv->channels.lock, flags); for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; -@@ -131,9 +228,48 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) +@@ -131,9 +247,48 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) } spin_unlock_irqrestore(&dev_priv->channels.lock, flags); @@ -1758,7 +4865,7 @@ index 6b149c0..d4f4206 100644 spin_unlock(&priv->lock); } diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c -index 37e21d2..a32b301 100644 +index 37e21d2..7950bac 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -95,13 +95,41 @@ nv50_graph_init_regs__nv(struct drm_device *dev) @@ -1824,15 +4931,41 @@ index 37e21d2..a32b301 100644 ret = nv50_graph_init_ctxctl(dev); if (ret) -@@ -526,11 +555,11 @@ nv86_graph_tlb_flush(struct drm_device *dev) - - static struct nouveau_enum nv50_mp_exec_error_names[] = +@@ -409,12 +438,7 @@ static int + nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { +- struct nouveau_page_flip_state s; +- +- if (!nouveau_finish_page_flip(chan, &s)) { +- /* XXX - Do something here */ +- } +- ++ nouveau_finish_page_flip(chan, NULL); + return 0; + } + +@@ -479,7 +503,7 @@ nv50_graph_tlb_flush(struct drm_device *dev) + } + + void +-nv86_graph_tlb_flush(struct drm_device *dev) ++nv84_graph_tlb_flush(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; +@@ -524,13 +548,12 @@ nv86_graph_tlb_flush(struct drm_device *dev) + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + } + +-static struct nouveau_enum nv50_mp_exec_error_names[] = +-{ - { 3, "STACK_UNDERFLOW" }, - { 4, "QUADON_ACTIVE" }, - { 8, "TIMEOUT" }, - { 0x10, "INVALID_OPCODE" }, - { 0x40, "BREAKPOINT" }, ++static struct nouveau_enum nv50_mp_exec_error_names[] = { + { 3, "STACK_UNDERFLOW", NULL }, + { 4, "QUADON_ACTIVE", NULL }, + { 8, "TIMEOUT", NULL }, @@ -1841,7 +4974,7 @@ index 37e21d2..a32b301 100644 {} }; -@@ -558,47 +587,47 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = { +@@ -558,47 +581,47 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = { /* There must be a *lot* of these. Will take some time to gather them up. */ struct nouveau_enum nv50_data_error_names[] = { @@ -1930,7 +5063,16 @@ index 37e21d2..a32b301 100644 {} }; -@@ -678,7 +707,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, +@@ -639,7 +662,7 @@ nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) + nv_rd32(dev, addr + 0x20); + pc = nv_rd32(dev, addr + 0x24); + oplow = nv_rd32(dev, addr + 0x70); +- ophigh= nv_rd32(dev, addr + 0x74); ++ ophigh = nv_rd32(dev, addr + 0x74); + NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " + "TP %d MP %d: ", tpid, i); + nouveau_enum_print(nv50_mp_exec_error_names, status); +@@ -678,7 +701,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, tps++; switch (type) { case 6: /* texture error... unknown for now */ @@ -1938,7 +5080,7 @@ index 37e21d2..a32b301 100644 if (display) { NV_ERROR(dev, "magic set %d:\n", i); for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) -@@ -701,7 +729,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, +@@ -701,7 +723,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); @@ -1946,7 +5088,7 @@ index 37e21d2..a32b301 100644 /* 2d engine destination */ if (ustatus & 0x00000010) { if (display) { -@@ -912,10 +939,10 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid +@@ -912,10 +933,10 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid printk("\n"); NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" " %08x %08x %08x\n", @@ -1961,7 +5103,7 @@ index 37e21d2..a32b301 100644 } -@@ -1044,6 +1071,7 @@ nv50_graph_isr(struct drm_device *dev) +@@ -1044,6 +1065,7 @@ nv50_graph_isr(struct drm_device *dev) NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " "class 0x%04x mthd 0x%04x data 0x%08x\n", chid, inst, subc, class, mthd, data); @@ -1969,8 +5111,87 @@ index 37e21d2..a32b301 100644 } } +diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c +index 336aab2..de9abff 100644 +--- a/drivers/gpu/drm/nouveau/nv50_grctx.c ++++ b/drivers/gpu/drm/nouveau/nv50_grctx.c +@@ -747,7 +747,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + gr_def(ctx, offset + 0x64, 0x0000001f); + gr_def(ctx, offset + 0x68, 0x0000000f); + gr_def(ctx, offset + 0x6c, 0x0000000f); +- } else if(dev_priv->chipset < 0xa0) { ++ } else if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, offset + 0x50, 1); + cp_ctx(ctx, offset + 0x70, 1); + } else { +@@ -924,7 +924,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) + dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */ + } else { + dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */ +- } ++ } + dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */ + if (dev_priv->chipset != 0x50) + dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */ +@@ -1803,9 +1803,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) + xf_emit(ctx, 1, 0); /* 1ff */ + xf_emit(ctx, 8, 0); /* 0? */ + xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ +- } +- else +- { ++ } else { + xf_emit(ctx, 0xc, 0); /* RO */ + /* SEEK */ + xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ +@@ -2836,7 +2834,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) + xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ + if (IS_NVA3F(dev_priv->chipset)) + xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ +- if(dev_priv->chipset == 0x50) ++ if (dev_priv->chipset == 0x50) + xf_emit(ctx, 1, 0); /* ff */ + else + xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ +diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c +index e57caa2..fa94973 100644 +--- a/drivers/gpu/drm/nouveau/nv50_instmem.c ++++ b/drivers/gpu/drm/nouveau/nv50_instmem.c +@@ -300,7 +300,7 @@ nv50_instmem_resume(struct drm_device *dev) + } + + struct nv50_gpuobj_node { +- struct nouveau_vram *vram; ++ struct nouveau_mem *vram; + struct nouveau_vma chan_vma; + u32 align; + }; +diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c +index b4a5ecb..c25c593 100644 +--- a/drivers/gpu/drm/nouveau/nv50_sor.c ++++ b/drivers/gpu/drm/nouveau/nv50_sor.c +@@ -41,8 +41,7 @@ nv50_sor_disconnect(struct drm_encoder *encoder) + { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; + + if (!nv_encoder->crtc) +@@ -184,8 +183,7 @@ static void + nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) + { +- struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; +- struct nouveau_channel *evo = dev_priv->evo; ++ struct nouveau_channel *evo = nv50_display(encoder->dev)->master; + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct drm_device *dev = encoder->dev; + struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c -index 6144156..1f47c75 100644 +index 6144156..4fd3432 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c @@ -31,7 +31,6 @@ void @@ -1981,6 +5202,184 @@ index 6144156..1f47c75 100644 u64 phys = 0xdeadcafe00000000ULL; u32 coverage = 0; +@@ -58,10 +57,9 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, + } + + static inline u64 +-nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- u64 phys, u32 memtype, u32 target) ++nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) + { +- struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; ++ struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; + + phys |= 1; /* present */ + phys |= (u64)memtype << 40; +@@ -85,12 +83,13 @@ nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + + void + nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) + { ++ u32 comp = (mem->memtype & 0x180) >> 7; + u32 block; + int i; + +- phys = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0); ++ phys = nv50_vm_addr(vma, phys, mem->memtype, 0); + pte <<= 3; + cnt <<= 3; + +@@ -107,6 +106,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + + phys += block << (vma->node->type - 3); + cnt -= block; ++ if (comp) { ++ u32 tag = mem->tag->start + ((delta >> 16) * comp); ++ offset_h |= (tag << 17); ++ delta += block << (vma->node->type - 3); ++ } + + while (block) { + nv_wo32(pgt, pte + 0, offset_l); +@@ -119,11 +123,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + + void + nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- u32 pte, dma_addr_t *list, u32 cnt) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) + { + pte <<= 3; + while (cnt--) { +- u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2); ++ u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; +diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c +index 58e98ad..ffbc3d8 100644 +--- a/drivers/gpu/drm/nouveau/nv50_vram.c ++++ b/drivers/gpu/drm/nouveau/nv50_vram.c +@@ -48,42 +48,49 @@ nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) + } + + void +-nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram) ++nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; + struct nouveau_mm *mm = man->priv; + struct nouveau_mm_node *this; +- struct nouveau_vram *vram; ++ struct nouveau_mem *mem; + +- vram = *pvram; +- *pvram = NULL; +- if (unlikely(vram == NULL)) ++ mem = *pmem; ++ *pmem = NULL; ++ if (unlikely(mem == NULL)) + return; + + mutex_lock(&mm->mutex); +- while (!list_empty(&vram->regions)) { +- this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); ++ while (!list_empty(&mem->regions)) { ++ this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + + list_del(&this->rl_entry); + nouveau_mm_put(mm, this); + } ++ ++ if (mem->tag) { ++ drm_mm_put_block(mem->tag); ++ mem->tag = NULL; ++ } + mutex_unlock(&mm->mutex); + +- kfree(vram); ++ kfree(mem); + } + + int + nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, +- u32 type, struct nouveau_vram **pvram) ++ u32 memtype, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; + struct nouveau_mm *mm = man->priv; + struct nouveau_mm_node *r; +- struct nouveau_vram *vram; ++ struct nouveau_mem *mem; ++ int comp = (memtype & 0x300) >> 8; ++ int type = (memtype & 0x07f); + int ret; + + if (!types[type]) +@@ -92,32 +99,46 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, + align >>= 12; + size_nc >>= 12; + +- vram = kzalloc(sizeof(*vram), GFP_KERNEL); +- if (!vram) ++ mem = kzalloc(sizeof(*mem), GFP_KERNEL); ++ if (!mem) + return -ENOMEM; + +- INIT_LIST_HEAD(&vram->regions); +- vram->dev = dev_priv->dev; +- vram->memtype = type; +- vram->size = size; +- + mutex_lock(&mm->mutex); ++ if (comp) { ++ if (align == 16) { ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ int n = (size >> 4) * comp; ++ ++ mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); ++ if (mem->tag) ++ mem->tag = drm_mm_get_block(mem->tag, n, 0); ++ } ++ ++ if (unlikely(!mem->tag)) ++ comp = 0; ++ } ++ ++ INIT_LIST_HEAD(&mem->regions); ++ mem->dev = dev_priv->dev; ++ mem->memtype = (comp << 7) | type; ++ mem->size = size; ++ + do { + ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); +- nv50_vram_del(dev, &vram); ++ nv50_vram_del(dev, &mem); + return ret; + } + +- list_add_tail(&r->rl_entry, &vram->regions); ++ list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + +- r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); +- vram->offset = (u64)r->offset << 12; +- *pvram = vram; ++ r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); ++ mem->offset = (u64)r->offset << 12; ++ *pmem = mem; + return 0; + } + diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c index ec18ae1..fabc7fd 100644 --- a/drivers/gpu/drm/nouveau/nv84_crypt.c @@ -1993,10 +5392,107 @@ index ec18ae1..fabc7fd 100644 + nv50_fb_vm_trap(dev, show); } diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c -index e6f92c5..e9f8643 100644 +index e6f92c5..55a4245 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fifo.c +++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c -@@ -418,6 +418,12 @@ nvc0_fifo_isr(struct drm_device *dev) +@@ -116,7 +116,7 @@ nvc0_fifo_create_context(struct nouveau_channel *chan) + + /* allocate vram for control regs, map into polling area */ + ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, +- 0, 0, true, true, &fifoch->user); ++ 0, 0, &fifoch->user); + if (ret) + goto error; + +@@ -355,19 +355,57 @@ nvc0_fifo_init(struct drm_device *dev) + } + + struct nouveau_enum nvc0_fifo_fault_unit[] = { +- { 0, "PGRAPH" }, +- { 3, "PEEPHOLE" }, +- { 4, "BAR1" }, +- { 5, "BAR3" }, +- { 7, "PFIFO" }, ++ { 0x00, "PGRAPH" }, ++ { 0x03, "PEEPHOLE" }, ++ { 0x04, "BAR1" }, ++ { 0x05, "BAR3" }, ++ { 0x07, "PFIFO" }, ++ { 0x10, "PBSP" }, ++ { 0x11, "PPPP" }, ++ { 0x13, "PCOUNTER" }, ++ { 0x14, "PVP" }, ++ { 0x15, "PCOPY0" }, ++ { 0x16, "PCOPY1" }, ++ { 0x17, "PDAEMON" }, + {} + }; + + struct nouveau_enum nvc0_fifo_fault_reason[] = { +- { 0, "PT_NOT_PRESENT" }, +- { 1, "PT_TOO_SHORT" }, +- { 2, "PAGE_NOT_PRESENT" }, +- { 3, "VM_LIMIT_EXCEEDED" }, ++ { 0x00, "PT_NOT_PRESENT" }, ++ { 0x01, "PT_TOO_SHORT" }, ++ { 0x02, "PAGE_NOT_PRESENT" }, ++ { 0x03, "VM_LIMIT_EXCEEDED" }, ++ { 0x04, "NO_CHANNEL" }, ++ { 0x05, "PAGE_SYSTEM_ONLY" }, ++ { 0x06, "PAGE_READ_ONLY" }, ++ { 0x0a, "COMPRESSED_SYSRAM" }, ++ { 0x0c, "INVALID_STORAGE_TYPE" }, ++ {} ++}; ++ ++struct nouveau_enum nvc0_fifo_fault_hubclient[] = { ++ { 0x01, "PCOPY0" }, ++ { 0x02, "PCOPY1" }, ++ { 0x04, "DISPATCH" }, ++ { 0x05, "CTXCTL" }, ++ { 0x06, "PFIFO" }, ++ { 0x07, "BAR_READ" }, ++ { 0x08, "BAR_WRITE" }, ++ { 0x0b, "PVP" }, ++ { 0x0c, "PPPP" }, ++ { 0x0d, "PBSP" }, ++ { 0x11, "PCOUNTER" }, ++ { 0x12, "PDAEMON" }, ++ { 0x14, "CCACHE" }, ++ { 0x15, "CCACHE_POST" }, ++ {} ++}; ++ ++struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { ++ { 0x01, "TEX" }, ++ { 0x0c, "ESETUP" }, ++ { 0x0e, "CTXCTL" }, ++ { 0x0f, "PROP" }, + {} + }; + +@@ -385,12 +423,20 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) + u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); + u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); + u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); ++ u32 client = (stat & 0x00001f00) >> 8; + + NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", + (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); + nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); + printk("] from "); + nouveau_enum_print(nvc0_fifo_fault_unit, unit); ++ if (stat & 0x00000040) { ++ printk("/"); ++ nouveau_enum_print(nvc0_fifo_fault_hubclient, client); ++ } else { ++ printk("/GPC%d/", (stat & 0x1f000000) >> 24); ++ nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); ++ } + printk(" on channel 0x%010llx\n", (u64)inst << 12); + } + +@@ -418,6 +464,12 @@ nvc0_fifo_isr(struct drm_device *dev) { u32 stat = nv_rd32(dev, 0x002100); @@ -2009,7 +5505,7 @@ index e6f92c5..e9f8643 100644 if (stat & 0x10000000) { u32 units = nv_rd32(dev, 0x00259c); u32 u = units; -@@ -446,10 +452,15 @@ nvc0_fifo_isr(struct drm_device *dev) +@@ -446,10 +498,15 @@ nvc0_fifo_isr(struct drm_device *dev) stat &= ~0x20000000; } @@ -2028,10 +5524,111 @@ index e6f92c5..e9f8643 100644 - nv_wr32(dev, 0x2140, 0); } diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c -index eb18a7e..afa7afe 100644 +index eb18a7e..68f5c3f 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c -@@ -640,7 +640,6 @@ nvc0_graph_init(struct drm_device *dev) +@@ -200,15 +200,15 @@ nvc0_graph_create_context(struct nouveau_channel *chan) + for (i = 0; i < priv->grctx_size; i += 4) + nv_wo32(grctx, i, priv->grctx_vals[i / 4]); + +- nv_wo32(grctx, 0xf4, 0); +- nv_wo32(grctx, 0xf8, 0); +- nv_wo32(grctx, 0x10, grch->mmio_nr); +- nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst)); +- nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst)); +- nv_wo32(grctx, 0x1c, 1); +- nv_wo32(grctx, 0x20, 0); +- nv_wo32(grctx, 0x28, 0); +- nv_wo32(grctx, 0x2c, 0); ++ nv_wo32(grctx, 0xf4, 0); ++ nv_wo32(grctx, 0xf8, 0); ++ nv_wo32(grctx, 0x10, grch->mmio_nr); ++ nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst)); ++ nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst)); ++ nv_wo32(grctx, 0x1c, 1); ++ nv_wo32(grctx, 0x20, 0); ++ nv_wo32(grctx, 0x28, 0); ++ nv_wo32(grctx, 0x2c, 0); + pinstmem->flush(dev); + return 0; + +@@ -299,6 +299,14 @@ nvc0_graph_takedown(struct drm_device *dev) + } + + static int ++nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, ++ u32 class, u32 mthd, u32 data) ++{ ++ nouveau_finish_page_flip(chan, NULL); ++ return 0; ++} ++ ++static int + nvc0_graph_create(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -395,6 +403,7 @@ nvc0_graph_create(struct drm_device *dev) + nouveau_irq_register(dev, 25, nvc0_runk140_isr); + NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ + NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ ++ NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); + NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ + NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ + return 0; +@@ -443,28 +452,30 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; + int gpc; +- +- // TP ROP UNKVAL(magic_not_rop_nr) +- // 450: 4/0/0/0 2 3 +- // 460: 3/4/0/0 4 1 +- // 465: 3/4/4/0 4 7 +- // 470: 3/3/4/4 5 5 +- // 480: 3/4/4/4 6 6 +- +- // magicgpc918 +- // 450: 00200000 00000000001000000000000000000000 +- // 460: 00124925 00000000000100100100100100100101 +- // 465: 000ba2e9 00000000000010111010001011101001 +- // 470: 00092493 00000000000010010010010010010011 +- // 480: 00088889 00000000000010001000100010001001 +- +- /* filled values up to tp_total, remainder 0 */ +- // 450: 00003210 00000000 00000000 00000000 +- // 460: 02321100 00000000 00000000 00000000 +- // 465: 22111000 00000233 00000000 00000000 +- // 470: 11110000 00233222 00000000 00000000 +- // 480: 11110000 03332222 00000000 00000000 +- ++ ++ /* ++ * TP ROP UNKVAL(magic_not_rop_nr) ++ * 450: 4/0/0/0 2 3 ++ * 460: 3/4/0/0 4 1 ++ * 465: 3/4/4/0 4 7 ++ * 470: 3/3/4/4 5 5 ++ * 480: 3/4/4/4 6 6 ++ ++ * magicgpc918 ++ * 450: 00200000 00000000001000000000000000000000 ++ * 460: 00124925 00000000000100100100100100100101 ++ * 465: 000ba2e9 00000000000010111010001011101001 ++ * 470: 00092493 00000000000010010010010010010011 ++ * 480: 00088889 00000000000010001000100010001001 ++ ++ * filled values up to tp_total, remainder 0 ++ * 450: 00003210 00000000 00000000 00000000 ++ * 460: 02321100 00000000 00000000 00000000 ++ * 465: 22111000 00000233 00000000 00000000 ++ * 470: 11110000 00233222 00000000 00000000 ++ * 480: 11110000 03332222 00000000 00000000 ++ */ ++ + nv_wr32(dev, GPC_BCAST(0x0980), priv->magicgpc980[0]); + nv_wr32(dev, GPC_BCAST(0x0984), priv->magicgpc980[1]); + nv_wr32(dev, GPC_BCAST(0x0988), priv->magicgpc980[2]); +@@ -640,7 +651,6 @@ nvc0_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; @@ -2039,7 +5636,7 @@ index eb18a7e..afa7afe 100644 int ret; dev_priv->engine.graph.accel_blocked = true; -@@ -665,7 +664,6 @@ nvc0_graph_init(struct drm_device *dev) +@@ -665,13 +675,12 @@ nvc0_graph_init(struct drm_device *dev) if (ret) return ret; } @@ -2047,3 +5644,305 @@ index eb18a7e..afa7afe 100644 nvc0_graph_init_obj418880(dev); nvc0_graph_init_regs(dev); +- //nvc0_graph_init_unitplemented_magics(dev); ++ /*nvc0_graph_init_unitplemented_magics(dev);*/ + nvc0_graph_init_gpc_0(dev); +- //nvc0_graph_init_unitplemented_c242(dev); ++ /*nvc0_graph_init_unitplemented_c242(dev);*/ + + nv_wr32(dev, 0x400500, 0x00010001); + nv_wr32(dev, 0x400100, 0xffffffff); +@@ -730,9 +739,12 @@ nvc0_graph_isr(struct drm_device *dev) + u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); + + if (stat & 0x00000010) { +- NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d " +- "class 0x%04x mthd 0x%04x data 0x%08x\n", +- chid, inst, subc, class, mthd, data); ++ if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { ++ NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " ++ "subc %d class 0x%04x mthd 0x%04x " ++ "data 0x%08x\n", ++ chid, inst, subc, class, mthd, data); ++ } + nv_wr32(dev, 0x400100, 0x00000010); + stat &= ~0x00000010; + } +diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h +index 40e26f9..d32b385 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_graph.h ++++ b/drivers/gpu/drm/nouveau/nvc0_graph.h +@@ -28,11 +28,11 @@ + #define GPC_MAX 4 + #define TP_MAX 32 + +-#define ROP_BCAST(r) (0x408800 + (r)) +-#define ROP_UNIT(u,r) (0x410000 + (u) * 0x400 + (r)) +-#define GPC_BCAST(r) (0x418000 + (r)) +-#define GPC_UNIT(t,r) (0x500000 + (t) * 0x8000 + (r)) +-#define TP_UNIT(t,m,r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) ++#define ROP_BCAST(r) (0x408800 + (r)) ++#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) ++#define GPC_BCAST(r) (0x418000 + (r)) ++#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) ++#define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) + + struct nvc0_graph_priv { + u8 gpc_nr; +@@ -52,9 +52,9 @@ struct nvc0_graph_priv { + + struct nvc0_graph_chan { + struct nouveau_gpuobj *grctx; +- struct nouveau_gpuobj *unk408004; // 0x418810 too +- struct nouveau_gpuobj *unk40800c; // 0x419004 too +- struct nouveau_gpuobj *unk418810; // 0x419848 too ++ struct nouveau_gpuobj *unk408004; /* 0x418810 too */ ++ struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ ++ struct nouveau_gpuobj *unk418810; /* 0x419848 too */ + struct nouveau_gpuobj *mmio; + int mmio_nr; + }; +diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c +index f880ff7..6cede9f 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c ++++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c +@@ -1623,7 +1623,7 @@ nvc0_grctx_generate_rop(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + +- // ROPC_BROADCAST ++ /* ROPC_BROADCAST */ + nv_wr32(dev, 0x408800, 0x02802a3c); + nv_wr32(dev, 0x408804, 0x00000040); + nv_wr32(dev, 0x408808, 0x0003e00d); +@@ -1647,7 +1647,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) + { + int i; + +- // GPC_BROADCAST ++ /* GPC_BROADCAST */ + nv_wr32(dev, 0x418380, 0x00000016); + nv_wr32(dev, 0x418400, 0x38004e00); + nv_wr32(dev, 0x418404, 0x71e0ffff); +@@ -1728,7 +1728,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + +- // GPC_BROADCAST.TP_BROADCAST ++ /* GPC_BROADCAST.TP_BROADCAST */ + nv_wr32(dev, 0x419848, 0x00000000); + nv_wr32(dev, 0x419864, 0x0000012a); + nv_wr32(dev, 0x419888, 0x00000000); +@@ -1741,7 +1741,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev) + nv_wr32(dev, 0x419a1c, 0x00000000); + nv_wr32(dev, 0x419a20, 0x00000800); + if (dev_priv->chipset != 0xc0) +- nv_wr32(dev, 0x00419ac4, 0x0007f440); // 0xc3 ++ nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */ + nv_wr32(dev, 0x419b00, 0x0a418820); + nv_wr32(dev, 0x419b04, 0x062080e6); + nv_wr32(dev, 0x419b08, 0x020398a4); +@@ -1912,13 +1912,13 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + for (i = 1; i < 7; i++) + data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); + +- // GPC_BROADCAST ++ /* GPC_BROADCAST */ + nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) | + priv->magic_not_rop_nr); + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x418b08 + (i * 4), data[i]); + +- // GPC_BROADCAST.TP_BROADCAST ++ /* GPC_BROADCAST.TP_BROADCAST */ + nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) | + priv->magic_not_rop_nr | + data2[0]); +@@ -1926,7 +1926,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + for (i = 0; i < 6; i++) + nv_wr32(dev, 0x419b00 + (i * 4), data[i]); + +- // UNK78xx ++ /* UNK78xx */ + nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) | + priv->magic_not_rop_nr); + for (i = 0; i < 6; i++) +@@ -1944,7 +1944,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) + gpc = -1; + for (i = 0, gpc = -1; i < 32; i++) { + int ltp = i * (priv->tp_total - 1) / 32; +- ++ + do { + gpc = (gpc + 1) % priv->gpc_nr; + } while (!tpnr[gpc]); +diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c +index e4e83c2..a0a2a02 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_vm.c ++++ b/drivers/gpu/drm/nouveau/nvc0_vm.c +@@ -59,7 +59,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) + + void + nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) + { + u32 next = 1 << (vma->node->type - 8); + +@@ -75,11 +75,11 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + + void + nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, +- u32 pte, dma_addr_t *list, u32 cnt) ++ struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) + { + pte <<= 3; + while (cnt--) { +- u64 phys = nvc0_vm_addr(vma, *list++, 0, 5); ++ u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; +@@ -104,20 +104,26 @@ nvc0_vm_flush(struct nouveau_vm *vm) + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct drm_device *dev = vm->dev; + struct nouveau_vm_pgd *vpgd; +- u32 r100c80, engine; ++ u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; + + pinstmem->flush(vm->dev); + +- if (vm == dev_priv->chan_vm) +- engine = 1; +- else +- engine = 5; +- ++ spin_lock(&dev_priv->ramin_lock); + list_for_each_entry(vpgd, &vm->pgd_list, head) { +- r100c80 = nv_rd32(dev, 0x100c80); ++ /* looks like maybe a "free flush slots" counter, the ++ * faster you write to 0x100cbc to more it decreases ++ */ ++ if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { ++ NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", ++ nv_rd32(dev, 0x100c80), engine); ++ } + nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); + nv_wr32(dev, 0x100cbc, 0x80000000 | engine); +- if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80)) +- NV_ERROR(dev, "vm flush timeout eng %d\n", engine); ++ /* wait for flush to be queued? */ ++ if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { ++ NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", ++ nv_rd32(dev, 0x100c80), engine); ++ } + } ++ spin_unlock(&dev_priv->ramin_lock); + } +diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c +index 858eda5..67c6ec6 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_vram.c ++++ b/drivers/gpu/drm/nouveau/nvc0_vram.c +@@ -26,64 +26,78 @@ + #include "nouveau_drv.h" + #include "nouveau_mm.h" + ++/* 0 = unsupported ++ * 1 = non-compressed ++ * 3 = compressed ++ */ ++static const u8 types[256] = { ++ 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, ++ 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, ++ 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ++ 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, ++ 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, ++ 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, ++ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 ++}; ++ + bool + nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) + { +- switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { +- case 0x0000: +- case 0xfe00: +- case 0xdb00: +- case 0x1100: +- return true; +- default: +- break; +- } +- +- return false; ++ u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; ++ return likely((types[memtype] == 1)); + } + + int + nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, +- u32 type, struct nouveau_vram **pvram) ++ u32 type, struct nouveau_mem **pmem) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; + struct nouveau_mm *mm = man->priv; + struct nouveau_mm_node *r; +- struct nouveau_vram *vram; ++ struct nouveau_mem *mem; + int ret; + + size >>= 12; + align >>= 12; + ncmin >>= 12; + +- vram = kzalloc(sizeof(*vram), GFP_KERNEL); +- if (!vram) ++ mem = kzalloc(sizeof(*mem), GFP_KERNEL); ++ if (!mem) + return -ENOMEM; + +- INIT_LIST_HEAD(&vram->regions); +- vram->dev = dev_priv->dev; +- vram->memtype = type; +- vram->size = size; ++ INIT_LIST_HEAD(&mem->regions); ++ mem->dev = dev_priv->dev; ++ mem->memtype = (type & 0xff); ++ mem->size = size; + + mutex_lock(&mm->mutex); + do { + ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); +- nv50_vram_del(dev, &vram); ++ nv50_vram_del(dev, &mem); + return ret; + } + +- list_add_tail(&r->rl_entry, &vram->regions); ++ list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + +- r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); +- vram->offset = (u64)r->offset << 12; +- *pvram = vram; ++ r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); ++ mem->offset = (u64)r->offset << 12; ++ *pmem = mem; + return 0; + } + diff --git a/kernel.spec b/kernel.spec index 5ec21a5c2..fceb3af33 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 9 +%global baserelease 10 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1972,6 +1972,12 @@ fi # and build. %changelog +* Thu Mar 31 2011 Ben Skeggs 2.6.38-2.10 +- nouveau: nva3+ stability improvements +- nouveau: nvc0 "stutter" fixes +- nouveau: nv50/nvc0 page flipping +- nouveau: nv50 z compression + * Wed Mar 29 2011 Kyle McMartin 2.6.38.2-9 - Downgrade SCSI sd printk's about disk caching from KERN_ERR to KERN_NOTICE so they don't show up in our pretty quiet boot. Ray noticed them when From f3e795d08b538d7003317b95c0763fa44d82b83a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Apr 2011 11:27:29 +1000 Subject: [PATCH 21/99] ttm: add patch required by nouveau --- drm-ttm-move-notify.patch | 40 +++++++++++++++++++++++++++++++++++++++ kernel.spec | 7 ++++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 drm-ttm-move-notify.patch diff --git a/drm-ttm-move-notify.patch b/drm-ttm-move-notify.patch new file mode 100644 index 000000000..4d4206fdc --- /dev/null +++ b/drm-ttm-move-notify.patch @@ -0,0 +1,40 @@ +From e40ec45d67d32ce900dd6f2242675979593db18c Mon Sep 17 00:00:00 2001 +From: Ben Skeggs +Date: Tue, 18 Jan 2011 11:04:03 +1000 +Subject: [PATCH] drm/ttm: call driver move_notify() when doing system->tt bo moves + +Nouveau doesn't have enough information at ttm_backend_func.bind() time +to implement things like tiled GART, or to keep a buffer at a constant +address in the GPU virtual address space no matter where in physical +memory it's placed. + +To resolve this, nouveau will handle binding of all buffers to the GPU +itself from the move_notify() hook. This commit ensures it's called +for all buffer moves. + +Signed-off-by: Ben Skeggs +--- + drivers/gpu/drm/ttm/ttm_bo.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c +index af61fc2..0b6a55a 100644 +--- a/drivers/gpu/drm/ttm/ttm_bo.c ++++ b/drivers/gpu/drm/ttm/ttm_bo.c +@@ -406,11 +406,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, + } + + if (bo->mem.mem_type == TTM_PL_SYSTEM) { ++ if (bdev->driver->move_notify) ++ bdev->driver->move_notify(bo, mem); + bo->mem = *mem; + mem->mm_node = NULL; + goto moved; + } +- + } + + if (bdev->driver->move_notify) +-- +1.7.4.2 + diff --git a/kernel.spec b/kernel.spec index fceb3af33..c78f37a94 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 10 +%global baserelease 11 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -670,6 +670,7 @@ Patch1555: fix_xen_guest_on_old_EC2.patch # nouveau + drm fixes Patch1810: drm-nouveau-updates.patch +Patch1811: drm-ttm-move-notify.patch Patch1819: drm-intel-big-hammer.patch # intel drm is all merged upstream # fix for 945G corruption will hit stable eventually @@ -1300,6 +1301,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core # Nouveau DRM +ApplyPatch drm-ttm-move-notify.patch ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM @@ -1972,6 +1974,9 @@ fi # and build. %changelog +* Mon Apr 04 2011 Ben Skeggs 2.6.38-2.11 +- ttm: add patch from upstream to fix a recent nouveau issue + * Thu Mar 31 2011 Ben Skeggs 2.6.38-2.10 - nouveau: nva3+ stability improvements - nouveau: nvc0 "stutter" fixes From 91fab41dfb885a3fb0f56d5caa7e0594fc0d3c2e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 7 Apr 2011 12:43:44 +1000 Subject: [PATCH 22/99] nouveau: switch nv4x to use only lowmem --- drm-nouveau-updates.patch | 4 ++-- kernel.spec | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 9c032f4df..c426b80d5 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1680,7 +1680,7 @@ index 4a8ad13..86c2e37 100644 static inline void cp_pos(struct nouveau_grctx *ctx, int offset) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index b0fb9bd..9a91bf1 100644 +index b0fb9bd..07ee9af 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -152,7 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev) @@ -1705,7 +1705,7 @@ index b0fb9bd..9a91bf1 100644 + if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) + dma_bits = 40; + } else -+ if (drm_device_is_pcie(dev) && ++ if (0 && drm_device_is_pcie(dev) && + dev_priv->chipset != 0x40 && + dev_priv->chipset != 0x45) { + if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39))) diff --git a/kernel.spec b/kernel.spec index c78f37a94..86409b6d2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 11 +%global baserelease 12 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1974,6 +1974,9 @@ fi # and build. %changelog +* Thu Apr 07 2011 Ben Skeggs 2.6.38-2.12 +- nouveau: switch nv4x back to DMA32 only (rhbz#689825) + * Mon Apr 04 2011 Ben Skeggs 2.6.38-2.11 - ttm: add patch from upstream to fix a recent nouveau issue From aef9f107249468a3f12808a9f0eacc7e63bd6af0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 7 Apr 2011 14:07:30 +0200 Subject: [PATCH 23/99] i915: Add a no lvds quirk for the Asus EB1007, this fixes gnome-shell --- drm-intel-eeebox-eb1007-quirk.patch | 36 +++++++++++++++++++++++++++++ kernel.spec | 5 ++++ 2 files changed, 41 insertions(+) create mode 100644 drm-intel-eeebox-eb1007-quirk.patch diff --git a/drm-intel-eeebox-eb1007-quirk.patch b/drm-intel-eeebox-eb1007-quirk.patch new file mode 100644 index 000000000..9ae3604e7 --- /dev/null +++ b/drm-intel-eeebox-eb1007-quirk.patch @@ -0,0 +1,36 @@ +From ab737b006568d01204cc51368c7e2067eecb2cff Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 7 Apr 2011 13:31:57 +0200 +Subject: [PATCH] drm/i915: Add a no lvds quirk for the Asus EeeBox PC EB1007 + +I found this while figuring out why gnome-shell would not run on my +Asus EeeBox PC EB1007. As a standalone "pc" this device cleary does not have +an internal panel, yet it claims it does. Add a quirk to fix this. + +Signed-off-by: Hans de Goede +--- + drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index a562bd2..954822a 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -724,6 +724,14 @@ static const struct dmi_system_id intel_no_lvds[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "U800"), + }, + }, ++ { ++ .callback = intel_no_lvds_dmi_callback, ++ .ident = "Asus EeeBox PC EB1007", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), ++ }, ++ }, + + { } /* terminating entry */ + }; +-- +1.7.4.2 + diff --git a/kernel.spec b/kernel.spec index 86409b6d2..8a0e33b13 100644 --- a/kernel.spec +++ b/kernel.spec @@ -680,6 +680,7 @@ Patch1824: drm-intel-next.patch Patch1825: drm-intel-make-lvds-work.patch Patch1826: drm-intel-edp-fixes.patch Patch1827: drm-i915-gen4-has-non-power-of-two-strides.patch +Patch1828: drm-intel-eeebox-eb1007-quirk.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1314,6 +1315,7 @@ ApplyPatch drm-i915-fix-pipelined-fencing.patch # rhbz#681285 (i965: crash in brw_wm_surface_state.c::prepare_wm_surfaces() # where intelObj->mt == NULL) #ApplyPatch drm-i915-gen4-has-non-power-of-two-strides.patch +ApplyPatch drm-intel-eeebox-eb1007-quirk.patch # linux1394 git patches #ApplyPatch linux-2.6-firewire-git-update.patch @@ -1974,6 +1976,9 @@ fi # and build. %changelog +* Thu Apr 07 2011 Hans de Goede +- i915: Add a no lvds quirk for the Asus EB1007, this fixes gnome-shell + * Thu Apr 07 2011 Ben Skeggs 2.6.38-2.12 - nouveau: switch nv4x back to DMA32 only (rhbz#689825) From 304107e3d0dbc845c1343f71536694f66b889395 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 8 Apr 2011 14:48:37 +1000 Subject: [PATCH 24/99] nouveau: fix pcie nv3x --- drm-nouveau-updates.patch | 10 +++++----- kernel.spec | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index c426b80d5..61e11a490 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1680,7 +1680,7 @@ index 4a8ad13..86c2e37 100644 static inline void cp_pos(struct nouveau_grctx *ctx, int offset) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index b0fb9bd..07ee9af 100644 +index b0fb9bd..f017997 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -152,7 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev) @@ -1706,7 +1706,7 @@ index b0fb9bd..07ee9af 100644 + dma_bits = 40; + } else + if (0 && drm_device_is_pcie(dev) && -+ dev_priv->chipset != 0x40 && ++ dev_priv->chipset > 0x40 && + dev_priv->chipset != 0x45) { + if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39))) + dma_bits = 39; @@ -2277,7 +2277,7 @@ index 04e8fb7..f18cdfc 100644 #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) #define NV50_PDISPLAY_USER_PUT(i) ((i) * 0x1000 + 0x00640000) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 9a250eb..b410d31 100644 +index 9a250eb..2bf9686 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -74,8 +74,24 @@ nouveau_sgdma_clear(struct ttm_backend *be) @@ -2605,7 +2605,7 @@ index 9a250eb..b410d31 100644 - aper_size = 64 * 1024 * 1024; - else - aper_size = 512 * 1024 * 1024; -+ if (dev_priv->card_type >= NV_50 || drm_device_is_pcie(dev)) ++ if (dev_priv->card_type >= NV_40 && drm_device_is_pcie(dev)) + aper_size = 512 * 1024 * 1024; + else + aper_size = 64 * 1024 * 1024; @@ -2640,7 +2640,7 @@ index 9a250eb..b410d31 100644 + dev_priv->gart_info.func = &nv50_sgdma_backend; + } else + if (0 && drm_device_is_pcie(dev) && -+ dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { ++ dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) { + if (nv44_graph_class(dev)) { + dev_priv->gart_info.func = &nv44_sgdma_backend; + align = 512 * 1024; diff --git a/kernel.spec b/kernel.spec index 8a0e33b13..fcc710f37 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 12 +%global baserelease 13 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1976,6 +1976,9 @@ fi # and build. %changelog +* Fri Apr 08 2011 Ben Skeggs 2.6.38-2.13 +- nouveau: fix pcie nv3x (rhbz#692588) + * Thu Apr 07 2011 Hans de Goede - i915: Add a no lvds quirk for the Asus EB1007, this fixes gnome-shell From 7666e4b3f35384f8bcb3e23b5c8922bb29e27822 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 11 Apr 2011 17:27:48 +1000 Subject: [PATCH 25/99] x86: add upstream patch to fix MTRR on resume - will come via stable later. --- kernel.spec | 6 ++ linux-2.6-x86-fix-mtrr-resume.patch | 89 +++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 linux-2.6-x86-fix-mtrr-resume.patch diff --git a/kernel.spec b/kernel.spec index fcc710f37..3bac2bc1a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -619,6 +619,8 @@ Patch30: linux-2.6-tracehook.patch Patch31: linux-2.6-utrace.patch Patch32: linux-2.6-utrace-ptrace.patch +Patch60: linux-2.6-x86-fix-mtrr-resume.patch + Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch Patch151: sparc64_fix_build_errors_with_gcc460.patch @@ -1182,6 +1184,7 @@ ApplyPatch linux-2.6-utrace-ptrace.patch # Architecture patches # x86(-64) +ApplyPatch linux-2.6-x86-fix-mtrr-resume.patch # # Intel IOMMU @@ -1976,6 +1979,9 @@ fi # and build. %changelog +* Mon Apr 11 2011 Dave Airlie +- x86: add upstream patch to fix MTRR on resume - will come via stable later. + * Fri Apr 08 2011 Ben Skeggs 2.6.38-2.13 - nouveau: fix pcie nv3x (rhbz#692588) diff --git a/linux-2.6-x86-fix-mtrr-resume.patch b/linux-2.6-x86-fix-mtrr-resume.patch new file mode 100644 index 000000000..7c39e7631 --- /dev/null +++ b/linux-2.6-x86-fix-mtrr-resume.patch @@ -0,0 +1,89 @@ +From 84ac7cdbdd0f04df6b96153f7a79127fd6e45467 Mon Sep 17 00:00:00 2001 +From: Suresh Siddha +Date: Tue, 29 Mar 2011 15:38:12 -0700 +Subject: [PATCH] x86, mtrr, pat: Fix one cpu getting out of sync during resume + +On laptops with core i5/i7, there were reports that after resume +graphics workloads were performing poorly on a specific AP, while +the other cpu's were ok. This was observed on a 32bit kernel +specifically. + +Debug showed that the PAT init was not happening on that AP +during resume and hence it contributing to the poor workload +performance on that cpu. + +On this system, resume flow looked like this: + +1. BP starts the resume sequence and we reinit BP's MTRR's/PAT + early on using mtrr_bp_restore() + +2. Resume sequence brings all AP's online + +3. Resume sequence now kicks off the MTRR reinit on all the AP's. + +4. For some reason, between point 2 and 3, we moved from BP + to one of the AP's. My guess is that printk() during resume + sequence is contributing to this. We don't see similar + behavior with the 64bit kernel but there is no guarantee that + at this point the remaining resume sequence (after AP's bringup) + has to happen on BP. + +5. set_mtrr() was assuming that we are still on BP and skipped the + MTRR/PAT init on that cpu (because of 1 above) + +6. But we were on an AP and this led to not reprogramming PAT + on this cpu leading to bad performance. + +Fix this by doing unconditional mtrr_if->set_all() in set_mtrr() +during MTRR/PAT init. This might be unnecessary if we are still +running on BP. But it is of no harm and will guarantee that after +resume, all the cpu's will be in sync with respect to the +MTRR/PAT registers. + +Signed-off-by: Suresh Siddha +LKML-Reference: <1301438292-28370-1-git-send-email-eric@anholt.net> +Signed-off-by: Eric Anholt +Tested-by: Keith Packard +Cc: stable@kernel.org [v2.6.32+] +Signed-off-by: H. Peter Anvin +--- + arch/x86/kernel/cpu/mtrr/main.c | 20 +++++++++++++++----- + 1 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c +index 307dfbb..929739a 100644 +--- a/arch/x86/kernel/cpu/mtrr/main.c ++++ b/arch/x86/kernel/cpu/mtrr/main.c +@@ -293,14 +293,24 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ + + /* + * HACK! +- * We use this same function to initialize the mtrrs on boot. +- * The state of the boot cpu's mtrrs has been saved, and we want +- * to replicate across all the APs. +- * If we're doing that @reg is set to something special... ++ * ++ * We use this same function to initialize the mtrrs during boot, ++ * resume, runtime cpu online and on an explicit request to set a ++ * specific MTRR. ++ * ++ * During boot or suspend, the state of the boot cpu's mtrrs has been ++ * saved, and we want to replicate that across all the cpus that come ++ * online (either at the end of boot or resume or during a runtime cpu ++ * online). If we're doing that, @reg is set to something special and on ++ * this cpu we still do mtrr_if->set_all(). During boot/resume, this ++ * is unnecessary if at this point we are still on the cpu that started ++ * the boot/resume sequence. But there is no guarantee that we are still ++ * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be ++ * sure that we are in sync with everyone else. + */ + if (reg != ~0U) + mtrr_if->set(reg, base, size, type); +- else if (!mtrr_aps_delayed_init) ++ else + mtrr_if->set_all(); + + /* Wait for the others */ +-- +1.7.4.2 + From 6747df9c318f45cedc51e647cbe1a123cebf9e79 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Apr 2011 09:15:54 +1000 Subject: [PATCH 26/99] nouveau: fix locking issue --- drm-nouveau-fixes.patch | 168 ++++++++++++++++++++++++++++++++++++++ drm-nouveau-updates.patch | 38 +-------- kernel.spec | 5 ++ 3 files changed, 174 insertions(+), 37 deletions(-) create mode 100644 drm-nouveau-fixes.patch diff --git a/drm-nouveau-fixes.patch b/drm-nouveau-fixes.patch new file mode 100644 index 000000000..d74feb7d2 --- /dev/null +++ b/drm-nouveau-fixes.patch @@ -0,0 +1,168 @@ +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h +index 982d70b..c01e43f 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h +@@ -681,6 +681,9 @@ struct drm_nouveau_private { + /* For PFIFO and PGRAPH. */ + spinlock_t context_switch_lock; + ++ /* VM/PRAMIN flush, legacy PRAMIN aperture */ ++ spinlock_t vm_lock; ++ + /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ + struct nouveau_ramht *ramht; + struct nouveau_gpuobj *ramfc; +diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c +index 30b6544..2002a43 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_object.c ++++ b/drivers/gpu/drm/nouveau/nouveau_object.c +@@ -1013,19 +1013,20 @@ nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) + { + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_device *dev = gpuobj->dev; ++ unsigned long flags; + + if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { + u64 ptr = gpuobj->vinst + offset; + u32 base = ptr >> 16; + u32 val; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + if (dev_priv->ramin_base != base) { + dev_priv->ramin_base = base; + nv_wr32(dev, 0x001700, dev_priv->ramin_base); + } + val = nv_rd32(dev, 0x700000 + (ptr & 0xffff)); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + return val; + } + +@@ -1037,18 +1038,19 @@ nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) + { + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_device *dev = gpuobj->dev; ++ unsigned long flags; + + if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { + u64 ptr = gpuobj->vinst + offset; + u32 base = ptr >> 16; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + if (dev_priv->ramin_base != base) { + dev_priv->ramin_base = base; + nv_wr32(dev, 0x001700, dev_priv->ramin_base); + } + nv_wr32(dev, 0x700000 + (ptr & 0xffff), val); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + return; + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c +index a54fc43..a358dc5 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_state.c ++++ b/drivers/gpu/drm/nouveau/nouveau_state.c +@@ -646,6 +646,7 @@ nouveau_card_init(struct drm_device *dev) + spin_lock_init(&dev_priv->channels.lock); + spin_lock_init(&dev_priv->tile.lock); + spin_lock_init(&dev_priv->context_switch_lock); ++ spin_lock_init(&dev_priv->vm_lock); + + /* Make the CRTCs and I2C buses accessible */ + ret = engine->display.early_init(dev); +diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c +index e57caa2..53a4b40 100644 +--- a/drivers/gpu/drm/nouveau/nv50_instmem.c ++++ b/drivers/gpu/drm/nouveau/nv50_instmem.c +@@ -404,23 +404,25 @@ void + nv50_instmem_flush(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ unsigned long flags; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x00330c, 0x00000001); + if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) + NV_ERROR(dev, "PRAMIN flush timeout\n"); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } + + void + nv84_instmem_flush(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ unsigned long flags; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x070000, 0x00000001); + if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) + NV_ERROR(dev, "PRAMIN flush timeout\n"); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } + +diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c +index 6144156..248496f 100644 +--- a/drivers/gpu/drm/nouveau/nv50_vm.c ++++ b/drivers/gpu/drm/nouveau/nv50_vm.c +@@ -170,10 +170,11 @@ void + nv50_vm_flush_engine(struct drm_device *dev, int engine) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ unsigned long flags; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x100c80, (engine << 16) | 1); + if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) + NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } +diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c +index e4e83c2..10a5a99 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_vm.c ++++ b/drivers/gpu/drm/nouveau/nvc0_vm.c +@@ -104,20 +104,27 @@ nvc0_vm_flush(struct nouveau_vm *vm) + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct drm_device *dev = vm->dev; + struct nouveau_vm_pgd *vpgd; +- u32 r100c80, engine; ++ unsigned long flags; ++ u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; + + pinstmem->flush(vm->dev); + +- if (vm == dev_priv->chan_vm) +- engine = 1; +- else +- engine = 5; +- ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + list_for_each_entry(vpgd, &vm->pgd_list, head) { +- r100c80 = nv_rd32(dev, 0x100c80); ++ /* looks like maybe a "free flush slots" counter, the ++ * faster you write to 0x100cbc to more it decreases ++ */ ++ if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { ++ NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", ++ nv_rd32(dev, 0x100c80), engine); ++ } + nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); + nv_wr32(dev, 0x100cbc, 0x80000000 | engine); +- if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80)) +- NV_ERROR(dev, "vm flush timeout eng %d\n", engine); ++ /* wait for flush to be queued? */ ++ if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { ++ NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", ++ nv_rd32(dev, 0x100c80), engine); ++ } + } ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 61e11a490..60f8d4d64 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -5777,7 +5777,7 @@ index f880ff7..6cede9f 100644 gpc = (gpc + 1) % priv->gpc_nr; } while (!tpnr[gpc]); diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c -index e4e83c2..a0a2a02 100644 +index e4e83c2..69af0ba 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vm.c +++ b/drivers/gpu/drm/nouveau/nvc0_vm.c @@ -59,7 +59,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) @@ -5803,42 +5803,6 @@ index e4e83c2..a0a2a02 100644 nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; -@@ -104,20 +104,26 @@ nvc0_vm_flush(struct nouveau_vm *vm) - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; - struct drm_device *dev = vm->dev; - struct nouveau_vm_pgd *vpgd; -- u32 r100c80, engine; -+ u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; - - pinstmem->flush(vm->dev); - -- if (vm == dev_priv->chan_vm) -- engine = 1; -- else -- engine = 5; -- -+ spin_lock(&dev_priv->ramin_lock); - list_for_each_entry(vpgd, &vm->pgd_list, head) { -- r100c80 = nv_rd32(dev, 0x100c80); -+ /* looks like maybe a "free flush slots" counter, the -+ * faster you write to 0x100cbc to more it decreases -+ */ -+ if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { -+ NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", -+ nv_rd32(dev, 0x100c80), engine); -+ } - nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); - nv_wr32(dev, 0x100cbc, 0x80000000 | engine); -- if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80)) -- NV_ERROR(dev, "vm flush timeout eng %d\n", engine); -+ /* wait for flush to be queued? */ -+ if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { -+ NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", -+ nv_rd32(dev, 0x100c80), engine); -+ } - } -+ spin_unlock(&dev_priv->ramin_lock); - } diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c index 858eda5..67c6ec6 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vram.c diff --git a/kernel.spec b/kernel.spec index 3bac2bc1a..0895262ec 100644 --- a/kernel.spec +++ b/kernel.spec @@ -671,6 +671,7 @@ Patch1555: fix_xen_guest_on_old_EC2.patch # DRM # nouveau + drm fixes +Patch1809: drm-nouveau-fixes.patch Patch1810: drm-nouveau-updates.patch Patch1811: drm-ttm-move-notify.patch Patch1819: drm-intel-big-hammer.patch @@ -1306,6 +1307,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # Nouveau DRM ApplyPatch drm-ttm-move-notify.patch +ApplyOptionalPatch drm-nouveau-fixes.patch ApplyOptionalPatch drm-nouveau-updates.patch # Intel DRM @@ -1979,6 +1981,9 @@ fi # and build. %changelog +* Tue Apr 12 2011 Ben Skeggs 2.6.38-2.14 +- nouveau: correct lock ordering problem + * Mon Apr 11 2011 Dave Airlie - x86: add upstream patch to fix MTRR on resume - will come via stable later. From e92d339e5546d3c659cab46abb045bab2dcef2eb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Apr 2011 09:19:23 +1000 Subject: [PATCH 27/99] bump baserelease --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index 0895262ec..7fccd8f32 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 13 +%global baserelease 14 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching From 9dde67c33a461e121574b1e90dbbca23bbcfafc3 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 11 Apr 2011 20:44:23 -0400 Subject: [PATCH 28/99] fix suspend to disk broken by 2.6.38.y --- kernel.spec | 8 ++++ ...tialize-mmu_cr4_features-during-boot.patch | 46 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 x86-hibernate-initialize-mmu_cr4_features-during-boot.patch diff --git a/kernel.spec b/kernel.spec index 7fccd8f32..8c1fa731f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -738,6 +738,8 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch +Patch12307: x86-hibernate-initialize-mmu_cr4_features-during-boot.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1373,6 +1375,9 @@ ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch +# fix hibernate broken by 2.6.38.y +ApplyPatch x86-hibernate-initialize-mmu_cr4_features-during-boot.patch + # END OF PATCH APPLICATIONS %endif @@ -1981,6 +1986,9 @@ fi # and build. %changelog +* Tue Apr 12 2011 Kyle McMartin +- fix hibernate which was broken by 2.6.38.y (korg#32222) + * Tue Apr 12 2011 Ben Skeggs 2.6.38-2.14 - nouveau: correct lock ordering problem diff --git a/x86-hibernate-initialize-mmu_cr4_features-during-boot.patch b/x86-hibernate-initialize-mmu_cr4_features-during-boot.patch new file mode 100644 index 000000000..ddccca117 --- /dev/null +++ b/x86-hibernate-initialize-mmu_cr4_features-during-boot.patch @@ -0,0 +1,46 @@ +From 157db94a095cbfa84a1932d516930f4371e7fab5 Mon Sep 17 00:00:00 2001 +From: H. Peter Anvin +Date: Wed, 6 Apr 2011 13:10:02 -0700 +Subject: [PATCH] x86, hibernate: Initialize mmu_cr4_features during boot + +Restore the initialization of mmu_cr4_features during boot, which was +removed without comment in checkin e5f15b45ddf3afa2bbbb10c7ea34fb32b6de0a0e + +x86: Cleanup highmap after brk is concluded + +thereby breaking resume from hibernate. This restores previous +functionality in approximately the same place, and corrects the +reading of %cr4 on pre-CPUID hardware (%cr4 exists if and only if +CPUID is supported.) + +However, part of the problem is that the hibernate suspend/resume +sequence should manage the save/restore of %cr4 explicitly. + +Signed-off-by: H. Peter Anvin +Cc: Rafael J. Wysocki +Cc: Stefano Stabellini +Cc: Yinghai Lu +LKML-Reference: <201104020154.57136.rjw@sisk.pl> +--- + arch/x86/kernel/setup.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index e543fe9..4e59873 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1013,6 +1013,11 @@ void __init setup_arch(char **cmdline_p) + paging_init(); + x86_init.paging.pagetable_setup_done(swapper_pg_dir); + ++ if (boot_cpu_data.cpuid_level >= 0) { ++ /* A CPU has %cr4 if and only if it has CPUID */ ++ mmu_cr4_features = read_cr4(); ++ } ++ + #ifdef CONFIG_X86_32 + /* sync back kernel address range */ + clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, +-- +1.7.4.2 + From 894d7acd63af60129aea67778e067c3a5e1060a8 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 13 Apr 2011 14:35:13 -0400 Subject: [PATCH 29/99] Linux 2.6.38.3-rc1 --- kernel.spec | 13 ++++++++----- sources | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/kernel.spec b/kernel.spec index 8c1fa731f..58b96571c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 14 +%global baserelease 15 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,9 +63,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -1187,7 +1187,7 @@ ApplyPatch linux-2.6-utrace-ptrace.patch # Architecture patches # x86(-64) -ApplyPatch linux-2.6-x86-fix-mtrr-resume.patch +#ApplyPatch linux-2.6-x86-fix-mtrr-resume.patch # # Intel IOMMU @@ -1250,7 +1250,7 @@ ApplyPatch linux-2.6-defaults-pci_use_crs.patch # enable ASPM by default on hardware we expect to work ApplyPatch linux-2.6-defaults-aspm.patch # rhbz #683156 -ApplyPatch pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch +#ApplyPatch pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch # ApplyPatch pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch @@ -1986,6 +1986,9 @@ fi # and build. %changelog +* Wed Apr 13 2011 Chuck Ebbert 2.6.38.3-15.rc1 +- Linux 2.6.38.3-rc1 + * Tue Apr 12 2011 Kyle McMartin - fix hibernate which was broken by 2.6.38.y (korg#32222) diff --git a/sources b/sources index e0d168044..704de0174 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 599badab31c4920d4122133208c810d7 patch-2.6.38.2.bz2 +f28dc8a539697b344cb43caed68488ed patch-2.6.38.3-rc1.bz2 From 1e374f7f2b8b107c08896e51fd69fa113d81e401 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 14 Apr 2011 19:41:55 -0400 Subject: [PATCH 30/99] Linux 2.6.38.3 --- ...15-gen4-has-non-power-of-two-strides.patch | 69 --------- kernel.spec | 25 ++-- linux-2.6-x86-fix-mtrr-resume.patch | 89 ----------- ...os-if-not-disabled-from-command-line.patch | 89 ----------- runtime_pm_fixups.patch | 138 ------------------ sources | 3 +- 6 files changed, 12 insertions(+), 401 deletions(-) delete mode 100644 drm-i915-gen4-has-non-power-of-two-strides.patch delete mode 100644 linux-2.6-x86-fix-mtrr-resume.patch delete mode 100644 pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch delete mode 100644 runtime_pm_fixups.patch diff --git a/drm-i915-gen4-has-non-power-of-two-strides.patch b/drm-i915-gen4-has-non-power-of-two-strides.patch deleted file mode 100644 index f111614bc..000000000 --- a/drm-i915-gen4-has-non-power-of-two-strides.patch +++ /dev/null @@ -1,69 +0,0 @@ -From bea96046b4245e9abd65ed7acfed9adfd5f6c639 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Thu, 3 Mar 2011 23:43:02 +0000 -Subject: [PATCH] drm/i915: Gen4+ has non-power-of-two strides - -In c2e0eb16707, we started checking that the buffer was the correct size -for tiled access by ensuring that the size was a multiple of tiles. -However, gen4+ complicates the issue by allowing any multiple of 4096 -bytes for the stride and so the simple check based on a power-of-two -stride was failing for valid bo. - -Reported-by: Dan Williams -Reported-by: Robert Hooker -Cc: Daniel Vetter -Signed-off-by: Chris Wilson ---- - drivers/gpu/drm/i915/i915_gem_tiling.c | 29 ++++++++++++++--------------- - 1 files changed, 14 insertions(+), 15 deletions(-) - -diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c -index 79a04fd..654f350 100644 ---- a/drivers/gpu/drm/i915/i915_gem_tiling.c -+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c -@@ -215,6 +215,19 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) - } - } - -+ if (INTEL_INFO(dev)->gen >= 4) { -+ /* 965+ just needs multiples of tile width */ -+ if (stride & (tile_width - 1)) -+ return false; -+ } else { -+ /* Pre-965 needs power of two tile widths */ -+ if (stride < tile_width) -+ return false; -+ -+ if (stride & (stride - 1)) -+ return false; -+ } -+ - if (IS_GEN2(dev) || - (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) - tile_height = 32; -@@ -226,21 +239,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) - tile_height *= 2; - - /* Size needs to be aligned to a full tile row */ -- if (size & (tile_height * stride - 1)) -- return false; -- -- /* 965+ just needs multiples of tile width */ -- if (INTEL_INFO(dev)->gen >= 4) { -- if (stride & (tile_width - 1)) -- return false; -- return true; -- } -- -- /* Pre-965 needs power of two tile widths */ -- if (stride < tile_width) -- return false; -- -- if (stride & (stride - 1)) -+ if (size % (tile_height * stride)) - return false; - - return true; --- -1.7.4.1 - diff --git a/kernel.spec b/kernel.spec index 58b96571c..6d2060b94 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 15 +%global baserelease 16 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -65,7 +65,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 3 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -619,8 +619,6 @@ Patch30: linux-2.6-tracehook.patch Patch31: linux-2.6-utrace.patch Patch32: linux-2.6-utrace-ptrace.patch -Patch60: linux-2.6-x86-fix-mtrr-resume.patch - Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch Patch151: sparc64_fix_build_errors_with_gcc460.patch @@ -682,7 +680,6 @@ Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open Patch1825: drm-intel-make-lvds-work.patch Patch1826: drm-intel-edp-fixes.patch -Patch1827: drm-i915-gen4-has-non-power-of-two-strides.patch Patch1828: drm-intel-eeebox-eb1007-quirk.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -729,8 +726,6 @@ Patch12200: acpi_reboot.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch -Patch12205: runtime_pm_fixups.patch -Patch12206: pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch Patch12207: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1187,7 +1182,6 @@ ApplyPatch linux-2.6-utrace-ptrace.patch # Architecture patches # x86(-64) -#ApplyPatch linux-2.6-x86-fix-mtrr-resume.patch # # Intel IOMMU @@ -1249,8 +1243,6 @@ ApplyPatch linux-2.6-defaults-pci_no_msi.patch ApplyPatch linux-2.6-defaults-pci_use_crs.patch # enable ASPM by default on hardware we expect to work ApplyPatch linux-2.6-defaults-aspm.patch -# rhbz #683156 -#ApplyPatch pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch # ApplyPatch pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch @@ -1319,9 +1311,6 @@ ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch drm-intel-edp-fixes.patch ApplyPatch drm-i915-fix-pipelined-fencing.patch -# rhbz#681285 (i965: crash in brw_wm_surface_state.c::prepare_wm_surfaces() -# where intelObj->mt == NULL) -#ApplyPatch drm-i915-gen4-has-non-power-of-two-strides.patch ApplyPatch drm-intel-eeebox-eb1007-quirk.patch # linux1394 git patches @@ -1365,7 +1354,6 @@ ApplyPatch acpi_reboot.patch #ApplyPatch linux-2.6-usb-pci-autosuspend.patch ### Broken by implicit notify support & ACPICA rebase ###ApplyPatch linux-2.6-enable-more-pci-autosuspend.patch -#ApplyPatch runtime_pm_fixups.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch @@ -1986,6 +1974,15 @@ fi # and build. %changelog +* Thu Apr 14 2011 Chuck Ebbert 2.6.38.3-16 +- Linux 2.6.38.3 +- Drop merged patches: + linux-2.6-x86-fix-mtrr-resume.patch + pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch +- Drop some obsolete patches: + runtime_pm_fixups.patch + drm-i915-gen4-has-non-power-of-two-strides.patch' + * Wed Apr 13 2011 Chuck Ebbert 2.6.38.3-15.rc1 - Linux 2.6.38.3-rc1 diff --git a/linux-2.6-x86-fix-mtrr-resume.patch b/linux-2.6-x86-fix-mtrr-resume.patch deleted file mode 100644 index 7c39e7631..000000000 --- a/linux-2.6-x86-fix-mtrr-resume.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 84ac7cdbdd0f04df6b96153f7a79127fd6e45467 Mon Sep 17 00:00:00 2001 -From: Suresh Siddha -Date: Tue, 29 Mar 2011 15:38:12 -0700 -Subject: [PATCH] x86, mtrr, pat: Fix one cpu getting out of sync during resume - -On laptops with core i5/i7, there were reports that after resume -graphics workloads were performing poorly on a specific AP, while -the other cpu's were ok. This was observed on a 32bit kernel -specifically. - -Debug showed that the PAT init was not happening on that AP -during resume and hence it contributing to the poor workload -performance on that cpu. - -On this system, resume flow looked like this: - -1. BP starts the resume sequence and we reinit BP's MTRR's/PAT - early on using mtrr_bp_restore() - -2. Resume sequence brings all AP's online - -3. Resume sequence now kicks off the MTRR reinit on all the AP's. - -4. For some reason, between point 2 and 3, we moved from BP - to one of the AP's. My guess is that printk() during resume - sequence is contributing to this. We don't see similar - behavior with the 64bit kernel but there is no guarantee that - at this point the remaining resume sequence (after AP's bringup) - has to happen on BP. - -5. set_mtrr() was assuming that we are still on BP and skipped the - MTRR/PAT init on that cpu (because of 1 above) - -6. But we were on an AP and this led to not reprogramming PAT - on this cpu leading to bad performance. - -Fix this by doing unconditional mtrr_if->set_all() in set_mtrr() -during MTRR/PAT init. This might be unnecessary if we are still -running on BP. But it is of no harm and will guarantee that after -resume, all the cpu's will be in sync with respect to the -MTRR/PAT registers. - -Signed-off-by: Suresh Siddha -LKML-Reference: <1301438292-28370-1-git-send-email-eric@anholt.net> -Signed-off-by: Eric Anholt -Tested-by: Keith Packard -Cc: stable@kernel.org [v2.6.32+] -Signed-off-by: H. Peter Anvin ---- - arch/x86/kernel/cpu/mtrr/main.c | 20 +++++++++++++++----- - 1 files changed, 15 insertions(+), 5 deletions(-) - -diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c -index 307dfbb..929739a 100644 ---- a/arch/x86/kernel/cpu/mtrr/main.c -+++ b/arch/x86/kernel/cpu/mtrr/main.c -@@ -293,14 +293,24 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ - - /* - * HACK! -- * We use this same function to initialize the mtrrs on boot. -- * The state of the boot cpu's mtrrs has been saved, and we want -- * to replicate across all the APs. -- * If we're doing that @reg is set to something special... -+ * -+ * We use this same function to initialize the mtrrs during boot, -+ * resume, runtime cpu online and on an explicit request to set a -+ * specific MTRR. -+ * -+ * During boot or suspend, the state of the boot cpu's mtrrs has been -+ * saved, and we want to replicate that across all the cpus that come -+ * online (either at the end of boot or resume or during a runtime cpu -+ * online). If we're doing that, @reg is set to something special and on -+ * this cpu we still do mtrr_if->set_all(). During boot/resume, this -+ * is unnecessary if at this point we are still on the cpu that started -+ * the boot/resume sequence. But there is no guarantee that we are still -+ * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be -+ * sure that we are in sync with everyone else. - */ - if (reg != ~0U) - mtrr_if->set(reg, base, size, type); -- else if (!mtrr_aps_delayed_init) -+ else - mtrr_if->set_all(); - - /* Wait for the others */ --- -1.7.4.2 - diff --git a/pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch b/pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch deleted file mode 100644 index 8dccd1a09..000000000 --- a/pci-acpi-report-aspm-support-to-bios-if-not-disabled-from-command-line.patch +++ /dev/null @@ -1,89 +0,0 @@ -From: Rafael J. Wysocki -Date: Sat, 5 Mar 2011 12:21:51 +0000 (+0100) -Subject: PCI/ACPI: Report ASPM support to BIOS if not disabled from command line -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8b8bae901ce23addbdcdb54fa1696fb2d049feb5 - -PCI/ACPI: Report ASPM support to BIOS if not disabled from command line - -We need to distinguish the situation in which ASPM support is -disabled from the command line or through .config from the situation -in which it is disabled, because the hardware or BIOS can't handle -it. In the former case we should not report ASPM support to the BIOS -through ACPI _OSC, but in the latter case we should do that. - -Introduce pcie_aspm_support_enabled() that can be used by -acpi_pci_root_add() to determine whether or not it should report ASPM -support to the BIOS through _OSC. - -Cc: stable@kernel.org -References: https://bugzilla.kernel.org/show_bug.cgi?id=29722 -References: https://bugzilla.kernel.org/show_bug.cgi?id=20232 -Reported-and-tested-by: Ortwin Glück -Reviewed-by: Kenji Kaneshige -Tested-by: Kenji Kaneshige -Signed-off-by: Rafael J. Wysocki -Signed-off-by: Jesse Barnes ---- - -diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c -index 8524939..c7358dd 100644 ---- a/drivers/acpi/pci_root.c -+++ b/drivers/acpi/pci_root.c -@@ -564,7 +564,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) - /* Indicate support for various _OSC capabilities. */ - if (pci_ext_cfg_avail(root->bus->self)) - flags |= OSC_EXT_PCI_CONFIG_SUPPORT; -- if (pcie_aspm_enabled()) -+ if (pcie_aspm_support_enabled()) - flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | - OSC_CLOCK_PWR_CAPABILITY_SUPPORT; - if (pci_msi_enabled()) -diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c -index 3188cd9..bbdb4fd 100644 ---- a/drivers/pci/pcie/aspm.c -+++ b/drivers/pci/pcie/aspm.c -@@ -69,6 +69,7 @@ struct pcie_link_state { - }; - - static int aspm_disabled, aspm_force, aspm_clear_state; -+static bool aspm_support_enabled = true; - static DEFINE_MUTEX(aspm_lock); - static LIST_HEAD(link_list); - -@@ -896,6 +897,7 @@ static int __init pcie_aspm_disable(char *str) - { - if (!strcmp(str, "off")) { - aspm_disabled = 1; -+ aspm_support_enabled = false; - printk(KERN_INFO "PCIe ASPM is disabled\n"); - } else if (!strcmp(str, "force")) { - aspm_force = 1; -@@ -930,3 +932,8 @@ int pcie_aspm_enabled(void) - } - EXPORT_SYMBOL(pcie_aspm_enabled); - -+bool pcie_aspm_support_enabled(void) -+{ -+ return aspm_support_enabled; -+} -+EXPORT_SYMBOL(pcie_aspm_support_enabled); -diff --git a/include/linux/pci.h b/include/linux/pci.h -index 16c9f2e..96f70d7 100644 ---- a/include/linux/pci.h -+++ b/include/linux/pci.h -@@ -1002,12 +1002,11 @@ extern bool pcie_ports_auto; - #endif - - #ifndef CONFIG_PCIEASPM --static inline int pcie_aspm_enabled(void) --{ -- return 0; --} -+static inline int pcie_aspm_enabled(void) { return 0; } -+static inline bool pcie_aspm_support_enabled(void) { return false; } - #else - extern int pcie_aspm_enabled(void); -+extern bool pcie_aspm_support_enabled(void); - #endif - - #ifdef CONFIG_PCIEAER diff --git a/runtime_pm_fixups.patch b/runtime_pm_fixups.patch deleted file mode 100644 index 1be6149d6..000000000 --- a/runtime_pm_fixups.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 141d0d01ab292d4ea3a6d5e96b4048e10e68c1d3 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Mon, 24 Jan 2011 13:01:57 -0500 -Subject: [PATCH] runtime_pm_fixups - ---- - drivers/acpi/bus.c | 3 ++- - drivers/acpi/pci_bind.c | 6 ++++++ - drivers/acpi/power.c | 5 ++++- - drivers/acpi/sleep.c | 2 +- - drivers/acpi/wakeup.c | 2 +- - drivers/pci/pci-acpi.c | 2 +- - include/acpi/acpi_bus.h | 2 +- - 7 files changed, 16 insertions(+), 6 deletions(-) - -diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c -index 7ced61f..e4e0114 100644 ---- a/drivers/acpi/bus.c -+++ b/drivers/acpi/bus.c -@@ -256,7 +256,8 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) - * a lower-powered state. - */ - if (state < device->power.state) { -- if (device->power.flags.power_resources) { -+ if (device->power.flags.power_resources && -+ !device->wakeup.run_wake_count) { - result = acpi_power_transition(device, state); - if (result) - goto end; -diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c -index 2ef0409..4b0bb68 100644 ---- a/drivers/acpi/pci_bind.c -+++ b/drivers/acpi/pci_bind.c -@@ -32,6 +32,8 @@ - #include - #include - -+#include "internal.h" -+ - #define _COMPONENT ACPI_PCI_COMPONENT - ACPI_MODULE_NAME("pci_bind"); - -@@ -65,6 +67,7 @@ static int acpi_pci_bind(struct acpi_device *device) - acpi_handle handle; - struct pci_bus *bus; - struct pci_dev *dev; -+ int state; - - dev = acpi_get_pci_dev(device->handle); - if (!dev) -@@ -87,6 +90,9 @@ static int acpi_pci_bind(struct acpi_device *device) - device->ops.unbind = acpi_pci_unbind; - } - -+ acpi_power_get_inferred_state(device, &state); -+ acpi_power_transition(device, state); -+ - /* - * Evaluate and parse _PRT, if exists. This code allows parsing of - * _PRT objects within the scope of non-bridge devices. Note that -diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c -index 9ac2a9f..cd6a8df 100644 ---- a/drivers/acpi/power.c -+++ b/drivers/acpi/power.c -@@ -412,7 +412,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state) - * State Wake) for the device, if present - * 2. Shutdown down the power resources - */ --int acpi_disable_wakeup_device_power(struct acpi_device *dev) -+int acpi_disable_wakeup_device_power(struct acpi_device *dev, int sleep_state) - { - int i, err = 0; - -@@ -435,6 +435,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev) - if (err) - goto out; - -+ if (sleep_state == ACPI_STATE_S0) -+ goto out; -+ - /* Close power resource */ - for (i = 0; i < dev->wakeup.resources.count; i++) { - int ret = acpi_power_off(dev->wakeup.resources.handles[i]); -diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c -index d6a8cd1..5d68dc0 100644 ---- a/drivers/acpi/sleep.c -+++ b/drivers/acpi/sleep.c -@@ -697,7 +697,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable) - - error = enable ? - acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : -- acpi_disable_wakeup_device_power(adev); -+ acpi_disable_wakeup_device_power(adev, acpi_target_sleep_state); - if (!error) - dev_info(dev, "wake-up capability %s by ACPI\n", - enable ? "enabled" : "disabled"); -diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c -index ed65014..a0cabc3 100644 ---- a/drivers/acpi/wakeup.c -+++ b/drivers/acpi/wakeup.c -@@ -73,7 +73,7 @@ void acpi_disable_wakeup_devices(u8 sleep_state) - ACPI_GPE_DISABLE); - - if (device_may_wakeup(&dev->dev)) -- acpi_disable_wakeup_device_power(dev); -+ acpi_disable_wakeup_device_power(dev, sleep_state); - } - } - -diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c -index 6fe0772..819fa7a 100644 ---- a/drivers/pci/pci-acpi.c -+++ b/drivers/pci/pci-acpi.c -@@ -302,7 +302,7 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable) - if (!--dev->wakeup.run_wake_count) { - acpi_disable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); -- acpi_disable_wakeup_device_power(dev); -+ acpi_disable_wakeup_device_power(dev, ACPI_STATE_S0); - } - } else { - error = -EALREADY; -diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h -index 78ca429..92d6e86 100644 ---- a/include/acpi/acpi_bus.h -+++ b/include/acpi/acpi_bus.h -@@ -379,7 +379,7 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); - #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) - - int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); --int acpi_disable_wakeup_device_power(struct acpi_device *dev); -+int acpi_disable_wakeup_device_power(struct acpi_device *dev, int state); - - #ifdef CONFIG_PM_OPS - int acpi_pm_device_sleep_state(struct device *, int *); --- -1.7.3.5 - diff --git a/sources b/sources index 704de0174..0e267b8a3 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -599badab31c4920d4122133208c810d7 patch-2.6.38.2.bz2 -f28dc8a539697b344cb43caed68488ed patch-2.6.38.3-rc1.bz2 +b3677121c4b5efcb8128c2000788d0aa patch-2.6.38.3.bz2 From 36477ddc42a12a82cf35088698e4457ea658f628 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Fri, 15 Apr 2011 10:52:11 -0400 Subject: [PATCH 31/99] drop unneeded patch --- kernel.spec | 9 ++-- ...tialize-mmu_cr4_features-during-boot.patch | 46 ------------------- 2 files changed, 4 insertions(+), 51 deletions(-) delete mode 100644 x86-hibernate-initialize-mmu_cr4_features-during-boot.patch diff --git a/kernel.spec b/kernel.spec index 6d2060b94..e1a08c547 100644 --- a/kernel.spec +++ b/kernel.spec @@ -733,8 +733,6 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch -Patch12307: x86-hibernate-initialize-mmu_cr4_features-during-boot.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1363,9 +1361,6 @@ ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch -# fix hibernate broken by 2.6.38.y -ApplyPatch x86-hibernate-initialize-mmu_cr4_features-during-boot.patch - # END OF PATCH APPLICATIONS %endif @@ -1974,6 +1969,10 @@ fi # and build. %changelog +* Fri Apr 15 2011 Kyle McMartin +- Drop x86-hibernate-initialize-mmu_cr4_features-during-boot.patch, + e5f15b45 was reverted in stable. + * Thu Apr 14 2011 Chuck Ebbert 2.6.38.3-16 - Linux 2.6.38.3 - Drop merged patches: diff --git a/x86-hibernate-initialize-mmu_cr4_features-during-boot.patch b/x86-hibernate-initialize-mmu_cr4_features-during-boot.patch deleted file mode 100644 index ddccca117..000000000 --- a/x86-hibernate-initialize-mmu_cr4_features-during-boot.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 157db94a095cbfa84a1932d516930f4371e7fab5 Mon Sep 17 00:00:00 2001 -From: H. Peter Anvin -Date: Wed, 6 Apr 2011 13:10:02 -0700 -Subject: [PATCH] x86, hibernate: Initialize mmu_cr4_features during boot - -Restore the initialization of mmu_cr4_features during boot, which was -removed without comment in checkin e5f15b45ddf3afa2bbbb10c7ea34fb32b6de0a0e - -x86: Cleanup highmap after brk is concluded - -thereby breaking resume from hibernate. This restores previous -functionality in approximately the same place, and corrects the -reading of %cr4 on pre-CPUID hardware (%cr4 exists if and only if -CPUID is supported.) - -However, part of the problem is that the hibernate suspend/resume -sequence should manage the save/restore of %cr4 explicitly. - -Signed-off-by: H. Peter Anvin -Cc: Rafael J. Wysocki -Cc: Stefano Stabellini -Cc: Yinghai Lu -LKML-Reference: <201104020154.57136.rjw@sisk.pl> ---- - arch/x86/kernel/setup.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index e543fe9..4e59873 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -1013,6 +1013,11 @@ void __init setup_arch(char **cmdline_p) - paging_init(); - x86_init.paging.pagetable_setup_done(swapper_pg_dir); - -+ if (boot_cpu_data.cpuid_level >= 0) { -+ /* A CPU has %cr4 if and only if it has CPUID */ -+ mmu_cr4_features = read_cr4(); -+ } -+ - #ifdef CONFIG_X86_32 - /* sync back kernel address range */ - clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY, --- -1.7.4.2 - From 78e43cbafc5f91fe564f44c2231ea43779bda0ba Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 19 Apr 2011 11:39:12 -0400 Subject: [PATCH 32/99] media_tree updates destined for 2.6.39 and 2.6.40, plus some hid goodness Signed-off-by: Jarod Wilson --- config-generic | 8 +- kernel.spec | 28 +- linux-2.6-v4l-dvb-add-lgdt3304-support.patch | 350 - linux-2.6-v4l-dvb-experimental.patch | 1245 +++ linux-2.6-v4l-dvb-ir-core-update.patch | 6741 --------------- linux-2.6-v4l-dvb-update.patch | 7725 ++++++++++++++++++ linux-2.6-v4l-dvb-uvcvideo-update.patch | 362 - 7 files changed, 8989 insertions(+), 7470 deletions(-) delete mode 100644 linux-2.6-v4l-dvb-add-lgdt3304-support.patch delete mode 100644 linux-2.6-v4l-dvb-ir-core-update.patch delete mode 100644 linux-2.6-v4l-dvb-uvcvideo-update.patch diff --git a/config-generic b/config-generic index 1a4649f08..61bee74ac 100644 --- a/config-generic +++ b/config-generic @@ -2675,9 +2675,6 @@ CONFIG_IR_JVC_DECODER=m CONFIG_IR_SONY_DECODER=m CONFIG_IR_RC5_SZ_DECODER=m CONFIG_IR_LIRC_CODEC=m -CONFIG_IR_IMON=m -CONFIG_IR_MCEUSB=m -CONFIG_IR_NUVOTON=m CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set @@ -3067,6 +3064,7 @@ CONFIG_HID_SONY=m CONFIG_HID_SUNPLUS=m CONFIG_HID_GREENASIA=m CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TIVO_SLIDE=m CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m @@ -4469,6 +4467,10 @@ CONFIG_IR_CORE=m CONFIG_IR_ENE=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_NUVOTON=m +CONFIG_IR_ITE_CIR=m # CONFIG_GPIO_SX150X is not set # CONFIG_MFD_STMPE is not set diff --git a/kernel.spec b/kernel.spec index e1a08c547..e60fab806 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 16 +%global baserelease 17 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -696,12 +696,6 @@ Patch2802: linux-2.6-silence-acpi-blacklist.patch Patch2899: linux-2.6-v4l-dvb-fixes.patch Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch -Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch - -Patch2910: linux-2.6-v4l-dvb-add-lgdt3304-support.patch -Patch2912: linux-2.6-v4l-dvb-ir-core-update.patch - -#Patch2916: lirc-staging-2.6.36-fixes.patch Patch2918: flexcop-fix-xlate_proc_name-warning.patch @@ -1323,13 +1317,6 @@ ApplyPatch linux-2.6-silence-acpi-blacklist.patch ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch -#ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch -#ApplyPatch linux-2.6-v4l-dvb-ir-core-update.patch - -###FIX###ApplyPatch linux-2.6-v4l-dvb-add-lgdt3304-support.patch - -# http://www.lirc.org/ -#ApplyOptionalPatch lirc-staging-2.6.36-fixes.patch # rhbz#664852 ApplyPatch flexcop-fix-xlate_proc_name-warning.patch @@ -1969,6 +1956,19 @@ fi # and build. %changelog +* Tue Apr 19 2011 Jarod Wilson +- Add basic support for full 32-bit NEC IR scancodes +- Add latest patches sent upstream for hid layer expansion and full + support for the TiVo Slide bluetooth/hid remote +- Add a TiVo IR remote keymap, use it by default with TiVo mceusb device +- Add ite-cir driver, nuke crappy old lirc_it* drivers +- Add an initial Apple remote keymap +- Add support for more Nuvoton IR hardware variants +- Overhaul lirc_zilog refcounting so it doesn't suck so badly anymore +- Clean up myriad of Hauppauge keymaps +- Make ir-kbd-i2c pass full rc5 scancodes when it can +- Misc minor v4l/dvb fixes + * Fri Apr 15 2011 Kyle McMartin - Drop x86-hibernate-initialize-mmu_cr4_features-during-boot.patch, e5f15b45 was reverted in stable. diff --git a/linux-2.6-v4l-dvb-add-lgdt3304-support.patch b/linux-2.6-v4l-dvb-add-lgdt3304-support.patch deleted file mode 100644 index 30c50434f..000000000 --- a/linux-2.6-v4l-dvb-add-lgdt3304-support.patch +++ /dev/null @@ -1,350 +0,0 @@ -From b71e18093e2e7f240797875c50c49552722f8825 Mon Sep 17 00:00:00 2001 -From: Jarod Wilson -Date: Mon, 15 Feb 2010 17:13:25 -0500 -Subject: [PATCH 1/2] dvb: add lgdt3304 support to lgdt3305 driver - -There's a currently-unused lgdt3304 demod driver, which leaves a lot to -be desired as far as functionality. The 3304 is unsurprisingly quite -similar to the 3305, and empirical testing yeilds far better results -and more complete functionality by merging 3304 support into the 3305 -driver. (For example, the current lgdt3304 driver lacks support for -signal strength, snr, ucblocks, etc., which we get w/the lgdt3305). - -For the moment, not dropping the lgdt3304 driver, and its still up to -a given device's config setup to choose which demod driver to use, but -I'd suggest dropping the 3304 driver entirely. - -As a follow-up to this patch, I've got another patch that adds support -for the KWorld PlusTV 340U (ATSC) em2870-based tuner stick, driving -its lgdt3304 demod via this lgdt3305 driver, which is what I used to -successfully test this patch with both VSB_8 and QAM_256 signals. - -A few pieces are still a touch crude, but I think its a solid start, -as well as much cleaner and more feature-complete than the existing -lgdt3304 driver. - -Signed-off-by: Jarod Wilson ---- - drivers/media/dvb/frontends/lgdt3305.c | 206 ++++++++++++++++++++++++++++++-- - drivers/media/dvb/frontends/lgdt3305.h | 6 + - 2 files changed, 203 insertions(+), 9 deletions(-) - -diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c -index fde8c59..40695e6 100644 ---- a/drivers/media/dvb/frontends/lgdt3305.c -+++ b/drivers/media/dvb/frontends/lgdt3305.c -@@ -1,5 +1,5 @@ - /* -- * Support for LGDT3305 - VSB/QAM -+ * Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM - * - * Copyright (C) 2008, 2009 Michael Krufky - * -@@ -357,7 +357,10 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state, - case QAM_256: - agcdelay = 0x046b; - rfbw = 0x8889; -- ifbw = 0x8888; -+ if (state->cfg->demod_chip == LGDT3305) -+ ifbw = 0x8888; -+ else -+ ifbw = 0x6666; - break; - default: - return -EINVAL; -@@ -409,8 +412,18 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state, - lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen); - - /* control agc function */ -- lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1); -- lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen); -+ switch (state->cfg->demod_chip) { -+ case LGDT3304: -+ lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1); -+ lgdt3305_set_reg_bit(state, 0x030e, 2, acqen); -+ break; -+ case LGDT3305: -+ lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1); -+ lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen); -+ break; -+ default: -+ return -EINVAL; -+ } - - return lgdt3305_rfagc_loop(state, param); - } -@@ -543,6 +556,11 @@ static int lgdt3305_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) - enable ? 0 : 1); - } - -+static int lgdt3304_sleep(struct dvb_frontend *fe) -+{ -+ return 0; -+} -+ - static int lgdt3305_sleep(struct dvb_frontend *fe) - { - struct lgdt3305_state *state = fe->demodulator_priv; -@@ -571,6 +589,55 @@ static int lgdt3305_sleep(struct dvb_frontend *fe) - return 0; - } - -+static int lgdt3304_init(struct dvb_frontend *fe) -+{ -+ struct lgdt3305_state *state = fe->demodulator_priv; -+ int ret; -+ -+ static struct lgdt3305_reg lgdt3304_init_data[] = { -+ { .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, }, -+ { .reg = 0x000d, .val = 0x02, }, -+ { .reg = 0x000e, .val = 0x02, }, -+ { .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, }, -+ { .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, }, -+ { .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, }, -+ { .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, }, -+ { .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, }, -+ { .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, }, -+ { .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, }, -+ { .reg = 0x0112, .val = 0x17, }, -+ { .reg = 0x0113, .val = 0x15, }, -+ { .reg = 0x0114, .val = 0x18, }, -+ { .reg = 0x0115, .val = 0xff, }, -+ { .reg = 0x0116, .val = 0x3c, }, -+ { .reg = 0x0214, .val = 0x67, }, -+ { .reg = 0x0424, .val = 0x8d, }, -+ { .reg = 0x0427, .val = 0x12, }, -+ { .reg = 0x0428, .val = 0x4f, }, -+ { .reg = LGDT3305_IFBW_1, .val = 0x80, }, -+ { .reg = LGDT3305_IFBW_2, .val = 0x00, }, -+ { .reg = 0x030a, .val = 0x08, }, -+ { .reg = 0x030b, .val = 0x9b, }, -+ { .reg = 0x030d, .val = 0x00, }, -+ { .reg = 0x030e, .val = 0x1c, }, -+ { .reg = 0x0314, .val = 0xe1, }, -+ { .reg = 0x000d, .val = 0x82, }, -+ { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, }, -+ { .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, }, -+ }; -+ -+ lg_dbg("\n"); -+ -+ ret = lgdt3305_write_regs(state, lgdt3304_init_data, -+ ARRAY_SIZE(lgdt3304_init_data)); -+ if (lg_fail(ret)) -+ goto fail; -+ -+ ret = lgdt3305_soft_reset(state); -+fail: -+ return ret; -+} -+ - static int lgdt3305_init(struct dvb_frontend *fe) - { - struct lgdt3305_state *state = fe->demodulator_priv; -@@ -639,6 +706,88 @@ fail: - return ret; - } - -+static int lgdt3304_set_parameters(struct dvb_frontend *fe, -+ struct dvb_frontend_parameters *param) -+{ -+ struct lgdt3305_state *state = fe->demodulator_priv; -+ int ret; -+ -+ lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation); -+ -+ if (fe->ops.tuner_ops.set_params) { -+ ret = fe->ops.tuner_ops.set_params(fe, param); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ if (lg_fail(ret)) -+ goto fail; -+ state->current_frequency = param->frequency; -+ } -+ -+ ret = lgdt3305_set_modulation(state, param); -+ if (lg_fail(ret)) -+ goto fail; -+ -+ ret = lgdt3305_passband_digital_agc(state, param); -+ if (lg_fail(ret)) -+ goto fail; -+ -+ ret = lgdt3305_agc_setup(state, param); -+ if (lg_fail(ret)) -+ goto fail; -+ -+ /* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */ -+ switch (param->u.vsb.modulation) { -+ case VSB_8: -+ lgdt3305_write_reg(state, 0x030d, 0x00); -+#if 1 -+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f); -+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c); -+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac); -+ lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba); -+#endif -+ break; -+ case QAM_64: -+ case QAM_256: -+ lgdt3305_write_reg(state, 0x030d, 0x14); -+#if 1 -+ ret = lgdt3305_set_if(state, param); -+ if (lg_fail(ret)) -+ goto fail; -+#endif -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+#if 0 -+ /* the set_if vsb formula doesn't work for the 3304, we end up sending -+ * 0x40851e07 instead of 0x4f0cacba (which works back to 94050, rather -+ * than 3250, in the case of the kworld 340u) */ -+ ret = lgdt3305_set_if(state, param); -+ if (lg_fail(ret)) -+ goto fail; -+#endif -+ -+ ret = lgdt3305_spectral_inversion(state, param, -+ state->cfg->spectral_inversion -+ ? 1 : 0); -+ if (lg_fail(ret)) -+ goto fail; -+ -+ state->current_modulation = param->u.vsb.modulation; -+ -+ ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode); -+ if (lg_fail(ret)) -+ goto fail; -+ -+ /* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */ -+ ret = lgdt3305_mpeg_mode_polarity(state, -+ state->cfg->tpclk_edge, -+ state->cfg->tpvalid_polarity); -+fail: -+ return ret; -+} -+ - static int lgdt3305_set_parameters(struct dvb_frontend *fe, - struct dvb_frontend_parameters *param) - { -@@ -847,6 +996,10 @@ static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status) - switch (state->current_modulation) { - case QAM_256: - case QAM_64: -+#if 0 /* needed w/3304 to set FE_HAS_SIGNAL */ -+ if (cr_lock) -+ *status |= FE_HAS_SIGNAL; -+#endif - ret = lgdt3305_read_fec_lock_status(state, &fec_lock); - if (lg_fail(ret)) - goto fail; -@@ -992,6 +1145,7 @@ static void lgdt3305_release(struct dvb_frontend *fe) - kfree(state); - } - -+static struct dvb_frontend_ops lgdt3304_ops; - static struct dvb_frontend_ops lgdt3305_ops; - - struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, -@@ -1012,11 +1166,21 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, - state->cfg = config; - state->i2c_adap = i2c_adap; - -- memcpy(&state->frontend.ops, &lgdt3305_ops, -- sizeof(struct dvb_frontend_ops)); -+ switch (config->demod_chip) { -+ case LGDT3304: -+ memcpy(&state->frontend.ops, &lgdt3304_ops, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ case LGDT3305: -+ memcpy(&state->frontend.ops, &lgdt3305_ops, -+ sizeof(struct dvb_frontend_ops)); -+ break; -+ default: -+ goto fail; -+ } - state->frontend.demodulator_priv = state; - -- /* verify that we're talking to a lg dt3305 */ -+ /* verify that we're talking to a lg dt3304/5 */ - ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val); - if ((lg_fail(ret)) | (val == 0)) - goto fail; -@@ -1035,12 +1199,36 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config, - - return &state->frontend; - fail: -- lg_warn("unable to detect LGDT3305 hardware\n"); -+ lg_warn("unable to detect %s hardware\n", -+ config->demod_chip ? "LGDT3304" : "LGDT3305"); - kfree(state); - return NULL; - } - EXPORT_SYMBOL(lgdt3305_attach); - -+static struct dvb_frontend_ops lgdt3304_ops = { -+ .info = { -+ .name = "LG Electronics LGDT3304 VSB/QAM Frontend", -+ .type = FE_ATSC, -+ .frequency_min = 54000000, -+ .frequency_max = 858000000, -+ .frequency_stepsize = 62500, -+ .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB -+ }, -+ .i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl, -+ .init = lgdt3304_init, -+ .sleep = lgdt3304_sleep, -+ .set_frontend = lgdt3304_set_parameters, -+ .get_frontend = lgdt3305_get_frontend, -+ .get_tune_settings = lgdt3305_get_tune_settings, -+ .read_status = lgdt3305_read_status, -+ .read_ber = lgdt3305_read_ber, -+ .read_signal_strength = lgdt3305_read_signal_strength, -+ .read_snr = lgdt3305_read_snr, -+ .read_ucblocks = lgdt3305_read_ucblocks, -+ .release = lgdt3305_release, -+}; -+ - static struct dvb_frontend_ops lgdt3305_ops = { - .info = { - .name = "LG Electronics LGDT3305 VSB/QAM Frontend", -@@ -1064,7 +1252,7 @@ static struct dvb_frontend_ops lgdt3305_ops = { - .release = lgdt3305_release, - }; - --MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver"); -+MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver"); - MODULE_AUTHOR("Michael Krufky "); - MODULE_LICENSE("GPL"); - MODULE_VERSION("0.1"); -diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h -index 9cb11c9..a7f30c2 100644 ---- a/drivers/media/dvb/frontends/lgdt3305.h -+++ b/drivers/media/dvb/frontends/lgdt3305.h -@@ -41,6 +41,11 @@ enum lgdt3305_tp_valid_polarity { - LGDT3305_TP_VALID_HIGH = 1, - }; - -+enum lgdt_demod_chip_type { -+ LGDT3305 = 0, -+ LGDT3304 = 1, -+}; -+ - struct lgdt3305_config { - u8 i2c_addr; - -@@ -65,6 +70,7 @@ struct lgdt3305_config { - enum lgdt3305_mpeg_mode mpeg_mode; - enum lgdt3305_tp_clock_edge tpclk_edge; - enum lgdt3305_tp_valid_polarity tpvalid_polarity; -+ enum lgdt_demod_chip_type demod_chip; - }; - - #if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \ --- -1.6.6 - diff --git a/linux-2.6-v4l-dvb-experimental.patch b/linux-2.6-v4l-dvb-experimental.patch index e69de29bb..a5cc5911c 100644 --- a/linux-2.6-v4l-dvb-experimental.patch +++ b/linux-2.6-v4l-dvb-experimental.patch @@ -0,0 +1,1245 @@ +commit 02210203eb4df7fdf1156b24fcf2b7e2a20bf29c +Author: Jarod Wilson +Date: Tue Apr 19 15:47:34 2011 -0400 + + [media] mceusb: Formosa e017 device has no tx + + Per hardware provided to me, the Formosa Industrial Computing eHome + Infrared Receiver, 0x147a:0xe017, has no tx capability, it is rx only. + + Thanks go to Paul Rae for the hardware. + + Signed-off-by: Jarod Wilson + +commit 5919687ea8e0d3ee093b6edc4e24e30c1a8a60dc +Author: Jarod Wilson +Date: Tue Apr 19 14:31:40 2011 -0400 + + hid: flesh out support for tivo slide remote + + This patch finishes off adding full support for the TiVo Slide remote, + which is a mostly pure HID device from the perspective of the kernel. + There are a few mappings that use a vendor-specific usage page, and a + few keys in the consumer usage page that I think make sense to remap + slightly, to better fit their key labels' intended use. Doing this in a + stand-alone hid-tivo.c makes the modifications only matter for this + specific device. + + What's actually connected to the computer is a Broadcom-made usb dongle, + which has an embedded hub, bluetooth adapter, mouse and keyboard + devices. You pair with the dongle, then the remote sends data that its + converted into HID on the keyboard interface (the mouse interface + doesn't do anything interesting, so far as I can tell). + + lsusb for this device: + Bus 004 Device 005: ID 0a5c:2190 Broadcom Corp. + Bus 004 Device 004: ID 0a5c:4503 Broadcom Corp. + Bus 004 Device 003: ID 150a:1201 + Bus 004 Device 002: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth) + + Speaking of the keyboard interface, the remote actually does contain a + keyboard as well. The top slides away, revealing a reasonably functional + qwerty keyboard (not unlike many slide cell phones), thus the product + name. + + Applies cleanly to hid master, tested w/a 2.6.38.3-based Fedora kernel + and a 2.6.32-based Red Hat Enterprise Linux 6 kernel. + + CC: Jiri Kosina + Signed-off-by: Jarod Wilson + +commit f5d27c83d8b1d1db7d727d4d33ae3df1357c0f03 +Author: Jarod Wilson +Date: Thu Mar 24 17:08:00 2011 -0400 + + rc: add an Apple remote keymap + + Signed-off-by: Jarod Wilson + +commit 9942d577525ebac939c155aaeb18e97e1282c923 +Author: Jarod Wilson +Date: Tue Apr 12 12:38:27 2011 -0400 + + [media] rc/nuvoton-cir: enable CIR on w83667hg chip variant + + Thanks to some excellent investigative work by Douglas Clowes, it was + uncovered that the older w83667hg Nuvoton chip functions with this + driver after actually enabling the CIR function via its multi-function + chip config register. The CIR and CIR wide-band sensor enable bits are + just in a different place on this hardware, so we only poke register + 0x27 on 677 hardware now, and we poke register 0x2c on the 667 now. + + Reported-by: Douglas Clowes + Signed-off-by: Jarod Wilson + +commit 92e839f5added53445aa2c447d69ea1c399e3113 +Author: Jarod Wilson +Date: Tue Apr 12 13:00:07 2011 -0400 + + [media] rc/nuvoton-cir: only warn about unknown chips + + There are additional chip IDs that report a PNP ID of NTN0530, which we + were refusing to load on. Instead, lets just warn if we encounter an + unknown chip, as there's a chance it will work just fine. + + Also, expand the list of known hardware to include both an earlier and a + later generation chip that this driver should function with. Douglas has + an older w83667hg variant, that with a touch more work, will be + supported by this driver, and Lutz has a newer w83677hg variant that + works without any further modifications to the driver. + + Reported-by: Douglas Clowes + Reported-by: Lutz Sammer + Signed-off-by: Jarod Wilson + +commit 8cc98ca72fe0a5c0a5299057edf24690c6940098 +Author: Jarod Wilson +Date: Tue Apr 5 17:42:30 2011 -0400 + + [media] rc: further key name standardization + + Use the newly introduced KEY_IMAGES where appropriate, and standardize + on KEY_MEDIA for media center/application launcher button (such as the + Windows logo key on the Windows Media Center Ed. remotes). + + Signed-off-by: Jarod Wilson + +commit 29d1ac85998862cc4cb7629461358e932363c358 +Author: Jarod Wilson +Date: Thu Mar 24 15:43:45 2011 -0400 + + lirc_sasem: key debug spew off debug modparam + + Signed-off-by: Jarod Wilson + +commit 9965e8d8e0035e56e11e1ad6c359877e51749b34 +Author: Jarod Wilson +Date: Thu Mar 24 11:56:16 2011 -0400 + + ttusb-budget: driver has a debug param, use it + + Remove DEBUG define, key debug spew off of the module's debug param that + already exists. + + Signed-off-by: Jarod Wilson + +commit 10fabf1f9cf8c1d1b579ab549bf4429ad13e0219 +Author: Jarod Wilson +Date: Thu Mar 24 11:54:41 2011 -0400 + + drx397xD: remove unused DEBUG define + + Signed-off-by: Jarod Wilson + +commit aa17ba00097df21cd0392e8aea41e93460e25007 +Author: Jarod Wilson +Date: Thu Mar 24 11:59:10 2011 -0400 + + mceusb: tivo transceiver should default to tivo keymap + + Signed-off-by: Jarod Wilson + +commit 02a5f7ed83b1da82f78b759a293cd15170afe611 +Author: Jarod Wilson +Date: Thu Mar 24 11:58:48 2011 -0400 + + rc: add tivo/nero liquidtv keymap + + Signed-off-by: Jarod Wilson + +commit db27bf543d740530ca0c1ab9fa7f3386f998e87c +Author: Jarod Wilson +Date: Mon Apr 11 17:33:28 2011 -0400 + + hid: assorted usage updates from hut 1.12 + + I've got a Tivo Slide bluetooth remote/dongle, which uses a fair number + of hid usages that aren't currently mapped in hid-input.c. I'd initially + written additions to hid-input.c with just this device in mind, + including some bits that were specific to the device. This go around, + I'm looking at adding/correcting as many generic HID usages from the HID + Usage Tables, version 1.12, as I can -- which also serves to enable all + but four of the buttons on the Tivo Slide remote[*]. + + Outside of fixing the obviously incorrect mapping of 0xc 0x45 from + KEY_RADIO to KEY_RIGHT, and making use of the new KEY_IMAGES (just added + in 2.6.39-rc4) for AL Image Browser instead of KEY_MEDIA, these are + purely additions, and thus should have no negative impact on any already + functional HID devices. Most of the added mappings seemed to be + perfectly logical to me, but there were a few that were mapped on more + of an "I think this makes the most sense" basis. + + [*] I'll handle the last four tivo buttons via an hid-tivo.c follow-up. + + CC: Dmitry Torokhov + CC: Jiri Kosina + Signed-off-by: Jarod Wilson + +commit 967bc222e57b94cf12cb4ad55383dec885f1755c +Author: Jarod Wilson +Date: Wed Apr 6 09:54:01 2011 -0400 + + input: add KEY_IMAGES specifically for AL Image Browser + + Many media center remotes have buttons intended for jumping straight to + one type of media browser or another -- commonly, images/photos/pictures, + audio/music, television, and movies. At present, remotes with an images + or photos or pictures button use any number of different keycodes which + sort of maybe fit. I've seen at least KEY_MEDIA, KEY_CAMERA, + KEY_GRAPHICSEDITOR and KEY_PRESENTATION. None of those seem quite right. + In my mind, KEY_MEDIA should be something more like a media center + application launcher (and I'd like to standardize on that for things + like the windows media center button on the mce remotes). KEY_CAMERA is + used in a lot of webcams, and typically means "take a picture now". + KEY_GRAPHICSEDITOR implies an editor, not a browser. KEY_PRESENTATION + might be the closest fit here, if you think "photo slide show", but it + may well be more intended for "run application in full-screen + presentation mode" or to launch something like magicpoint, I dunno. + And thus, I'd like to have a KEY_IMAGES, which matches the HID Usage AL + Image Browser, the meaning of which I think is crystal-clear. I believe + AL Audio Browser is already covered by KEY_AUDIO, and AL Movie Browser + by KEY_VIDEO, so I'm also adding appropriate comments next to those + keys. + + Signed-off-by: Jarod Wilson + +--- + drivers/hid/Kconfig | 6 + + drivers/hid/Makefile | 1 + + drivers/hid/hid-ids.h | 3 + + drivers/hid/hid-input.c | 60 ++++++++++-- + drivers/hid/hid-tivo.c | 89 ++++++++++++++++++ + drivers/media/dvb/dvb-usb/dibusb-common.c | 2 +- + drivers/media/dvb/dvb-usb/m920x.c | 16 ++-- + drivers/media/dvb/dvb-usb/nova-t-usb2.c | 2 +- + drivers/media/dvb/frontends/drx397xD.c | 1 - + drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 60 ++++++------- + drivers/media/rc/keymaps/Makefile | 2 + + drivers/media/rc/keymaps/rc-apple.c | 55 +++++++++++ + drivers/media/rc/keymaps/rc-avermedia-cardbus.c | 2 +- + drivers/media/rc/keymaps/rc-imon-mce.c | 2 +- + drivers/media/rc/keymaps/rc-imon-pad.c | 6 +- + .../media/rc/keymaps/rc-kworld-plus-tv-analog.c | 2 +- + drivers/media/rc/keymaps/rc-rc6-mce.c | 4 +- + drivers/media/rc/keymaps/rc-tivo.c | 98 ++++++++++++++++++++ + drivers/media/rc/mceusb.c | 16 +++- + drivers/media/rc/nuvoton-cir.c | 62 ++++++++++--- + drivers/media/rc/nuvoton-cir.h | 17 +++- + drivers/staging/lirc/lirc_sasem.c | 13 ++- + include/linux/input.h | 5 +- + include/media/rc-map.h | 2 + + 24 files changed, 439 insertions(+), 87 deletions(-) + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 2560f01..30a8cfd 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -492,6 +492,12 @@ config SMARTJOYPLUS_FF + Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to + enable force feedback support for it. + ++config HID_TIVO_SLIDE ++ tristate "TiVo Slide Bluetooth remote control support" ++ depends on USB_HID ++ ---help--- ++ Say Y if you have a TiVo Slide Bluetooth remote control. ++ + config HID_TOPSEED + tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" + depends on USB_HID +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 6efc2a0..7c1efa3 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -66,6 +66,7 @@ obj-$(CONFIG_HID_STANTUM) += hid-stantum.o + obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o + obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o + obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o ++obj-$(CONFIG_HID_TIVO) += hid-tivo.o + obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o + obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o + obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 92a0d61..8ece9eb 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -533,6 +533,9 @@ + + #define USB_VENDOR_ID_THRUSTMASTER 0x044f + ++#define USB_VENDOR_ID_TIVO 0x150a ++#define USB_DEVICE_ID_TIVO_SLIDE 0x1201 ++ + #define USB_VENDOR_ID_TOPSEED 0x0766 + #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 + +diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c +index 7f552bf..88d4703 100644 +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = { + 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, + 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, + 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, +- 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, ++ 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk, + unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, + unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, + unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, +- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, ++ unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk, + 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, + 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk + }; +@@ -365,6 +365,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x1: map_key_clear(KEY_POWER); break; + case 0x2: map_key_clear(KEY_SLEEP); break; + case 0x3: map_key_clear(KEY_WAKEUP); break; ++ case 0x4: map_key_clear(KEY_CONTEXT_MENU); break; ++ case 0x5: map_key_clear(KEY_MENU); break; ++ case 0x6: map_key_clear(KEY_PROG1); break; ++ case 0x7: map_key_clear(KEY_HELP); break; ++ case 0x8: map_key_clear(KEY_EXIT); break; ++ case 0x9: map_key_clear(KEY_SELECT); break; ++ case 0xa: map_key_clear(KEY_RIGHT); break; ++ case 0xb: map_key_clear(KEY_LEFT); break; ++ case 0xc: map_key_clear(KEY_UP); break; ++ case 0xd: map_key_clear(KEY_DOWN); break; ++ case 0xe: map_key_clear(KEY_POWER2); break; ++ case 0xf: map_key_clear(KEY_RESTART); break; + default: goto unknown; + } + break; +@@ -474,16 +486,39 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + } + break; + +- case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ ++ case HID_UP_CONSUMER: /* USB HUT v1.12, pages 75-84 */ + switch (usage->hid & HID_USAGE) { + case 0x000: goto ignore; ++ case 0x030: map_key_clear(KEY_POWER); break; ++ case 0x031: map_key_clear(KEY_RESTART); break; ++ case 0x032: map_key_clear(KEY_SLEEP); break; + case 0x034: map_key_clear(KEY_SLEEP); break; ++ case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE); break; + case 0x036: map_key_clear(BTN_MISC); break; + +- case 0x040: map_key_clear(KEY_MENU); break; +- case 0x045: map_key_clear(KEY_RADIO); break; +- ++ case 0x040: map_key_clear(KEY_MENU); break; /* Menu */ ++ case 0x041: map_key_clear(KEY_SELECT); break; /* Menu Pick */ ++ case 0x042: map_key_clear(KEY_UP); break; /* Menu Up */ ++ case 0x043: map_key_clear(KEY_DOWN); break; /* Menu Down */ ++ case 0x044: map_key_clear(KEY_LEFT); break; /* Menu Left */ ++ case 0x045: map_key_clear(KEY_RIGHT); break; /* Menu Right */ ++ case 0x046: map_key_clear(KEY_ESC); break; /* Menu Escape */ ++ case 0x047: map_key_clear(KEY_KPPLUS); break; /* Menu Value Increase */ ++ case 0x048: map_key_clear(KEY_KPMINUS); break; /* Menu Value Decrease */ ++ ++ case 0x060: map_key_clear(KEY_INFO); break; /* Data On Screen */ ++ case 0x061: map_key_clear(KEY_SUBTITLE); break; /* Closed Caption */ ++ case 0x063: map_key_clear(KEY_VCR); break; /* VCR/TV */ ++ case 0x065: map_key_clear(KEY_CAMERA); break; /* Snapshot */ ++ case 0x069: map_key_clear(KEY_RED); break; ++ case 0x06a: map_key_clear(KEY_GREEN); break; ++ case 0x06b: map_key_clear(KEY_BLUE); break; ++ case 0x06c: map_key_clear(KEY_YELLOW); break; ++ case 0x06d: map_key_clear(KEY_ZOOM); break; ++ ++ case 0x082: map_key_clear(KEY_VIDEO_NEXT); break; + case 0x083: map_key_clear(KEY_LAST); break; ++ case 0x084: map_key_clear(KEY_ENTER); break; + case 0x088: map_key_clear(KEY_PC); break; + case 0x089: map_key_clear(KEY_TV); break; + case 0x08a: map_key_clear(KEY_WWW); break; +@@ -517,6 +552,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x0b7: map_key_clear(KEY_STOPCD); break; + case 0x0b8: map_key_clear(KEY_EJECTCD); break; + case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break; ++ case 0x0b9: map_key_clear(KEY_SHUFFLE); break; ++ case 0x0bf: map_key_clear(KEY_SLOW); break; + + case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; + case 0x0e0: map_abs_clear(ABS_VOLUME); break; +@@ -524,6 +561,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x0e5: map_key_clear(KEY_BASSBOOST); break; + case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; + case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; ++ case 0x0f5: map_key_clear(KEY_SLOW); break; + + case 0x182: map_key_clear(KEY_BOOKMARKS); break; + case 0x183: map_key_clear(KEY_CONFIG); break; +@@ -540,6 +578,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x18e: map_key_clear(KEY_CALENDAR); break; + case 0x191: map_key_clear(KEY_FINANCE); break; + case 0x192: map_key_clear(KEY_CALC); break; ++ case 0x193: map_key_clear(KEY_PLAYER); break; + case 0x194: map_key_clear(KEY_FILE); break; + case 0x196: map_key_clear(KEY_WWW); break; + case 0x199: map_key_clear(KEY_CHAT); break; +@@ -548,8 +587,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x1a6: map_key_clear(KEY_HELP); break; + case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; + case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; +- case 0x1b6: map_key_clear(KEY_MEDIA); break; +- case 0x1b7: map_key_clear(KEY_SOUND); break; ++ case 0x1ae: map_key_clear(KEY_KEYBOARD); break; ++ case 0x1b6: map_key_clear(KEY_IMAGES); break; ++ case 0x1b7: map_key_clear(KEY_AUDIO); break; ++ case 0x1b8: map_key_clear(KEY_VIDEO); break; + case 0x1bc: map_key_clear(KEY_MESSENGER); break; + case 0x1bd: map_key_clear(KEY_INFO); break; + case 0x201: map_key_clear(KEY_NEW); break; +@@ -578,7 +619,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel + case 0x233: map_key_clear(KEY_SCROLLUP); break; + case 0x234: map_key_clear(KEY_SCROLLDOWN); break; + case 0x238: map_rel(REL_HWHEEL); break; ++ case 0x23d: map_key_clear(KEY_EDIT); break; + case 0x25f: map_key_clear(KEY_CANCEL); break; ++ case 0x269: map_key_clear(KEY_INSERT); break; ++ case 0x26a: map_key_clear(KEY_DELETE); break; + case 0x279: map_key_clear(KEY_REDO); break; + + case 0x289: map_key_clear(KEY_REPLY); break; +diff --git a/drivers/hid/hid-tivo.c b/drivers/hid/hid-tivo.c +new file mode 100644 +index 0000000..3d43c06 +--- /dev/null ++++ b/drivers/hid/hid-tivo.c +@@ -0,0 +1,89 @@ ++/* ++ * HID driver for TiVo Slide Bluetooth remote ++ * ++ * Copyright (c) 2011 Jarod Wilson ++ * based on the hid-topseed driver, which is in turn, based on hid-cherry... ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the Free ++ * Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ */ ++ ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++#define HID_UP_TIVOVENDOR 0xffff0000 ++#define tivo_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ ++ EV_KEY, (c)) ++ ++static int tivo_input_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ switch (usage->hid & HID_USAGE_PAGE) { ++ case HID_UP_TIVOVENDOR: ++ switch (usage->hid & HID_USAGE) { ++ /* TiVo button */ ++ case 0x3d: tivo_map_key_clear(KEY_MEDIA); break; ++ /* Live TV */ ++ case 0x3e: tivo_map_key_clear(KEY_TV); break; ++ /* Red thumbs down */ ++ case 0x41: tivo_map_key_clear(KEY_KPMINUS); break; ++ /* Green thumbs up */ ++ case 0x42: tivo_map_key_clear(KEY_KPPLUS); break; ++ default: ++ return 0; ++ } ++ break; ++ case HID_UP_CONSUMER: ++ switch (usage->hid & HID_USAGE) { ++ /* Enter/Last (default mapping: KEY_LAST) */ ++ case 0x083: tivo_map_key_clear(KEY_ENTER); break; ++ /* Info (default mapping: KEY_PROPS) */ ++ case 0x209: tivo_map_key_clear(KEY_INFO); break; ++ default: ++ return 0; ++ } ++ break; ++ default: ++ return 0; ++ } ++ ++ /* This means we found a matching mapping here, else, look in the ++ * standard hid mappings in hid-input.c */ ++ return 1; ++} ++ ++static const struct hid_device_id tivo_devices[] = { ++ /* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */ ++ { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, tivo_devices); ++ ++static struct hid_driver tivo_driver = { ++ .name = "tivo_slide", ++ .id_table = tivo_devices, ++ .input_mapping = tivo_input_mapping, ++}; ++ ++static int __init tivo_init(void) ++{ ++ return hid_register_driver(&tivo_driver); ++} ++ ++static void __exit tivo_exit(void) ++{ ++ hid_unregister_driver(&tivo_driver); ++} ++ ++module_init(tivo_init); ++module_exit(tivo_exit); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Jarod Wilson "); +diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c +index 956f7ae..4c2a689 100644 +--- a/drivers/media/dvb/dvb-usb/dibusb-common.c ++++ b/drivers/media/dvb/dvb-usb/dibusb-common.c +@@ -408,7 +408,7 @@ struct rc_map_table rc_map_dibusb_table[] = { + + { 0x8008, KEY_DVD }, + { 0x8009, KEY_AUDIO }, +- { 0x800a, KEY_MEDIA }, /* Pictures */ ++ { 0x800a, KEY_IMAGES }, /* Pictures */ + { 0x800b, KEY_VIDEO }, + + { 0x800c, KEY_BACK }, +diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c +index da9dc91..51bfd42 100644 +--- a/drivers/media/dvb/dvb-usb/m920x.c ++++ b/drivers/media/dvb/dvb-usb/m920x.c +@@ -632,9 +632,9 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { + { 0x16, KEY_POWER }, + { 0x17, KEY_FAVORITES }, + { 0x0f, KEY_TEXT }, +- { 0x48, KEY_MEDIA }, /* preview */ ++ { 0x48, KEY_PROGRAM }, /* preview */ + { 0x1c, KEY_EPG }, +- { 0x04, KEY_LIST }, /* record list */ ++ { 0x04, KEY_LIST }, /* record list */ + { 0x03, KEY_1 }, + { 0x01, KEY_2 }, + { 0x06, KEY_3 }, +@@ -674,14 +674,14 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { + { 0x0e, KEY_MUTE }, + /* { 0x49, KEY_LR }, */ /* L/R */ + { 0x07, KEY_SLEEP }, /* Hibernate */ +- { 0x08, KEY_MEDIA }, /* A/V */ +- { 0x0e, KEY_MENU }, /* Recall */ ++ { 0x08, KEY_VIDEO }, /* A/V */ ++ { 0x0e, KEY_MENU }, /* Recall */ + { 0x45, KEY_ZOOMIN }, + { 0x46, KEY_ZOOMOUT }, +- { 0x18, KEY_TV }, /* Red */ +- { 0x53, KEY_VCR }, /* Green */ +- { 0x5e, KEY_SAT }, /* Yellow */ +- { 0x5f, KEY_PLAYER }, /* Blue */ ++ { 0x18, KEY_RED }, /* Red */ ++ { 0x53, KEY_GREEN }, /* Green */ ++ { 0x5e, KEY_YELLOW }, /* Yellow */ ++ { 0x5f, KEY_BLUE }, /* Blue */ + }; + + /* DVB USB Driver stuff */ +diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c +index 9d3cd2d..bc350e9 100644 +--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c ++++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c +@@ -47,7 +47,7 @@ static struct rc_map_table rc_map_haupp_table[] = { + { 0x1e17, KEY_RIGHT }, + { 0x1e18, KEY_VIDEO }, + { 0x1e19, KEY_AUDIO }, +- { 0x1e1a, KEY_MEDIA }, ++ { 0x1e1a, KEY_IMAGES }, + { 0x1e1b, KEY_EPG }, + { 0x1e1c, KEY_TV }, + { 0x1e1e, KEY_NEXT }, +diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c +index a05007c..235ac72 100644 +--- a/drivers/media/dvb/frontends/drx397xD.c ++++ b/drivers/media/dvb/frontends/drx397xD.c +@@ -17,7 +17,6 @@ + * along with this program; If not, see . + */ + +-#define DEBUG /* uncomment if you want debugging output */ + #include + #include + #include +diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +index cbe2f0d..420bb42 100644 +--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c ++++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +@@ -52,7 +52,7 @@ + my TTUSB, so let it undef'd unless you want to implement another + frontend. never tested. + +- DEBUG: ++ debug: + define it to > 3 for really hardcore debugging. you probably don't want + this unless the device doesn't load at all. > 2 for bandwidth statistics. + */ +@@ -134,20 +134,19 @@ struct ttusb { + /* ugly workaround ... don't know why it's necessary to read */ + /* all result codes. */ + +-#define DEBUG 0 + static int ttusb_cmd(struct ttusb *ttusb, + const u8 * data, int len, int needresult) + { + int actual_len; + int err; +-#if DEBUG >= 3 + int i; + +- printk(">"); +- for (i = 0; i < len; ++i) +- printk(" %02x", data[i]); +- printk("\n"); +-#endif ++ if (debug >= 3) { ++ printk(KERN_DEBUG ">"); ++ for (i = 0; i < len; ++i) ++ printk(KERN_CONT " %02x", data[i]); ++ printk(KERN_CONT "\n"); ++ } + + if (mutex_lock_interruptible(&ttusb->semusb) < 0) + return -EAGAIN; +@@ -176,13 +175,15 @@ static int ttusb_cmd(struct ttusb *ttusb, + mutex_unlock(&ttusb->semusb); + return err; + } +-#if DEBUG >= 3 +- actual_len = ttusb->last_result[3] + 4; +- printk("<"); +- for (i = 0; i < actual_len; ++i) +- printk(" %02x", ttusb->last_result[i]); +- printk("\n"); +-#endif ++ ++ if (debug >= 3) { ++ actual_len = ttusb->last_result[3] + 4; ++ printk(KERN_DEBUG "<"); ++ for (i = 0; i < actual_len; ++i) ++ printk(KERN_CONT " %02x", ttusb->last_result[i]); ++ printk(KERN_CONT "\n"); ++ } ++ + if (!needresult) + mutex_unlock(&ttusb->semusb); + return 0; +@@ -636,16 +637,13 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) + ++ttusb->mux_state; + else { + ttusb->mux_state = 0; +-#if DEBUG > 3 +- if (ttusb->insync) +- printk("%02x ", data[-1]); +-#else + if (ttusb->insync) { +- printk("%s: lost sync.\n", ++ dprintk("%s: %02x\n", ++ __func__, data[-1]); ++ printk(KERN_INFO "%s: lost sync.\n", + __func__); + ttusb->insync = 0; + } +-#endif + } + break; + case 3: +@@ -744,6 +742,9 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) + static void ttusb_iso_irq(struct urb *urb) + { + struct ttusb *ttusb = urb->context; ++ struct usb_iso_packet_descriptor *d; ++ u8 *data; ++ int len, i; + + if (!ttusb->iso_streaming) + return; +@@ -755,21 +756,14 @@ static void ttusb_iso_irq(struct urb *urb) + #endif + + if (!urb->status) { +- int i; + for (i = 0; i < urb->number_of_packets; ++i) { +- struct usb_iso_packet_descriptor *d; +- u8 *data; +- int len; + numpkt++; + if (time_after_eq(jiffies, lastj + HZ)) { +-#if DEBUG > 2 +- printk +- ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n", +- numpkt * HZ / (jiffies - lastj), +- numts, numstuff, numsec, numinvalid, +- numts + numstuff + numsec + +- numinvalid); +-#endif ++ dprintk("frames/s: %lu (ts: %d, stuff %d, " ++ "sec: %d, invalid: %d, all: %d)\n", ++ numpkt * HZ / (jiffies - lastj), ++ numts, numstuff, numsec, numinvalid, ++ numts + numstuff + numsec + numinvalid); + numts = numstuff = numsec = numinvalid = 0; + lastj = jiffies; + numpkt = 0; +diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile +index 85cac7d..8c0cb70 100644 +--- a/drivers/media/rc/keymaps/Makefile ++++ b/drivers/media/rc/keymaps/Makefile +@@ -2,6 +2,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ + rc-alink-dtu-m.o \ + rc-anysee.o \ + rc-apac-viewcomp.o \ ++ rc-apple.o \ + rc-asus-pc39.o \ + rc-ati-tv-wonder-hd-600.o \ + rc-avermedia-a16d.o \ +@@ -77,6 +78,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ + rc-terratec-cinergy-xs.o \ + rc-terratec-slim.o \ + rc-tevii-nec.o \ ++ rc-tivo.o \ + rc-total-media-in-hand.o \ + rc-trekstor.o \ + rc-tt-1500.o \ +diff --git a/drivers/media/rc/keymaps/rc-apple.c b/drivers/media/rc/keymaps/rc-apple.c +new file mode 100644 +index 0000000..9fff474 +--- /dev/null ++++ b/drivers/media/rc/keymaps/rc-apple.c +@@ -0,0 +1,55 @@ ++/* rc-apple.c - Keytable for Apple remotes ++ * ++ * Copyright (c) 2011 by Jarod Wilson ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++ ++/* ++ * The Apple remotes use an NEC-ish protocol, but instead of having a ++ * command/not_command pair, they use a vendor ID of 0x77e1. Another byte ++ * is used for a pairing ID (0-255), to make it possible to have a system ++ * listen for only its specific remote. The last byte is the actual command ++ * byte. This table will only Just Work(tm) with remotes that have their ++ * pairing byte set to 0xc7 at the moment (one of my Apple remotes), but ++ * it can be trivially replaced from userspace with one using a different ++ * pairing byte value. ++ */ ++static struct rc_map_table apple[] = { ++ { 0x77e150c7, KEY_VOLUMEUP }, ++ { 0x77e130c7, KEY_VOLUMEDOWN }, ++ { 0x77e190c7, KEY_REWIND }, ++ { 0x77e160c7, KEY_FASTFORWARD }, ++ { 0x77e1a0c7, KEY_PLAYPAUSE }, ++ { 0x77e1c0c7, KEY_MENU }, ++}; ++ ++static struct rc_map_list apple_map = { ++ .map = { ++ .scan = apple, ++ .size = ARRAY_SIZE(apple), ++ .rc_type = RC_TYPE_NEC, ++ .name = RC_MAP_APPLE, ++ } ++}; ++ ++static int __init init_rc_map_apple(void) ++{ ++ return rc_map_register(&apple_map); ++} ++ ++static void __exit exit_rc_map_apple(void) ++{ ++ rc_map_unregister(&apple_map); ++} ++ ++module_init(init_rc_map_apple) ++module_exit(exit_rc_map_apple) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Jarod Wilson "); +diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c +index bdf97b7..22f54d4 100644 +--- a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c ++++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c +@@ -52,7 +52,7 @@ static struct rc_map_table avermedia_cardbus[] = { + { 0x28, KEY_SELECT }, /* Select */ + { 0x29, KEY_BLUE }, /* Blue/Picture */ + { 0x2a, KEY_BACKSPACE }, /* Back */ +- { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ ++ { 0x2b, KEY_VIDEO }, /* PIP (Picture-in-picture) */ + { 0x2c, KEY_DOWN }, + { 0x2e, KEY_DOT }, + { 0x2f, KEY_TV }, /* Live TV */ +diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c +index 937a819..0ea2aa1 100644 +--- a/drivers/media/rc/keymaps/rc-imon-mce.c ++++ b/drivers/media/rc/keymaps/rc-imon-mce.c +@@ -111,7 +111,7 @@ static struct rc_map_table imon_mce[] = { + { 0x800ff44d, KEY_TITLE }, + + { 0x800ff40c, KEY_POWER }, +- { 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */ ++ { 0x800ff40d, KEY_MEDIA }, /* Windows MCE button */ + + }; + +diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c +index 63d42bd..75d3843 100644 +--- a/drivers/media/rc/keymaps/rc-imon-pad.c ++++ b/drivers/media/rc/keymaps/rc-imon-pad.c +@@ -87,7 +87,7 @@ static struct rc_map_table imon_pad[] = { + + { 0x2b8515b7, KEY_VIDEO }, + { 0x299195b7, KEY_AUDIO }, +- { 0x2ba115b7, KEY_CAMERA }, ++ { 0x2ba115b7, KEY_IMAGES }, + { 0x28a515b7, KEY_TV }, + { 0x29a395b7, KEY_DVD }, + { 0x29a295b7, KEY_DVD }, +@@ -97,7 +97,7 @@ static struct rc_map_table imon_pad[] = { + { 0x2ba395b7, KEY_MENU }, + + { 0x288515b7, KEY_BOOKMARKS }, +- { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ ++ { 0x2ab715b7, KEY_CAMERA }, /* Thumbnail */ + { 0x298595b7, KEY_SUBTITLE }, + { 0x2b8595b7, KEY_LANGUAGE }, + +@@ -125,7 +125,7 @@ static struct rc_map_table imon_pad[] = { + { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ + { 0x02000065, KEY_COMPOSE }, /* RightMenu */ + { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ +- { 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */ ++ { 0x2ab195b7, KEY_MEDIA }, /* Go or MultiMon */ + { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ + }; + +diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +index 08d1831..7fa17a3 100644 +--- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c ++++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +@@ -17,7 +17,7 @@ + */ + + static struct rc_map_table kworld_plus_tv_analog[] = { +- { 0x0c, KEY_LEFTMETA }, /* Kworld key */ ++ { 0x0c, KEY_MEDIA }, /* Kworld key */ + { 0x16, KEY_CLOSECD }, /* -> ) */ + { 0x1d, KEY_POWER2 }, + +diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c +index 8dd519e..01b69bc 100644 +--- a/drivers/media/rc/keymaps/rc-rc6-mce.c ++++ b/drivers/media/rc/keymaps/rc-rc6-mce.c +@@ -30,7 +30,7 @@ static struct rc_map_table rc6_mce[] = { + { 0x800f040a, KEY_DELETE }, + { 0x800f040b, KEY_ENTER }, + { 0x800f040c, KEY_POWER }, /* PC Power */ +- { 0x800f040d, KEY_LEFTMETA }, /* Windows MCE button */ ++ { 0x800f040d, KEY_MEDIA }, /* Windows MCE button */ + { 0x800f040e, KEY_MUTE }, + { 0x800f040f, KEY_INFO }, + +@@ -87,7 +87,7 @@ static struct rc_map_table rc6_mce[] = { + + { 0x800f0465, KEY_POWER2 }, /* TV Power */ + { 0x800f046e, KEY_PLAYPAUSE }, +- { 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */ ++ { 0x800f046f, KEY_PLAYER }, /* Start media application (NEW) */ + + { 0x800f0480, KEY_BRIGHTNESSDOWN }, + { 0x800f0481, KEY_PLAYPAUSE }, +diff --git a/drivers/media/rc/keymaps/rc-tivo.c b/drivers/media/rc/keymaps/rc-tivo.c +new file mode 100644 +index 0000000..98ad085 +--- /dev/null ++++ b/drivers/media/rc/keymaps/rc-tivo.c +@@ -0,0 +1,98 @@ ++/* rc-tivo.c - Keytable for TiVo remotes ++ * ++ * Copyright (c) 2011 by Jarod Wilson ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++ ++/* ++ * Initial mapping is for the TiVo remote included in the Nero LiquidTV bundle, ++ * which also ships with a TiVo-branded IR transceiver, supported by the mceusb ++ * driver. Note that the remote uses an NEC-ish protocol, but instead of having ++ * a command/not_command pair, it has a vendor ID of 0xa10c, but some keys, the ++ * NEC extended checksums do pass, so the table presently has the intended ++ * values and the checksum-passed versions for those keys. ++ */ ++static struct rc_map_table tivo[] = { ++ { 0xa10c900f, KEY_MEDIA }, /* TiVo Button */ ++ { 0xa10c0807, KEY_POWER2 }, /* TV Power */ ++ { 0xa10c8807, KEY_TV }, /* Live TV/Swap */ ++ { 0xa10c2c03, KEY_VIDEO_NEXT }, /* TV Input */ ++ { 0xa10cc807, KEY_INFO }, ++ { 0xa10cfa05, KEY_CYCLEWINDOWS }, /* Window */ ++ { 0x0085305f, KEY_CYCLEWINDOWS }, ++ { 0xa10c6c03, KEY_EPG }, /* Guide */ ++ ++ { 0xa10c2807, KEY_UP }, ++ { 0xa10c6807, KEY_DOWN }, ++ { 0xa10ce807, KEY_LEFT }, ++ { 0xa10ca807, KEY_RIGHT }, ++ ++ { 0xa10c1807, KEY_SCROLLDOWN }, /* Red Thumbs Down */ ++ { 0xa10c9807, KEY_SELECT }, ++ { 0xa10c5807, KEY_SCROLLUP }, /* Green Thumbs Up */ ++ ++ { 0xa10c3807, KEY_VOLUMEUP }, ++ { 0xa10cb807, KEY_VOLUMEDOWN }, ++ { 0xa10cd807, KEY_MUTE }, ++ { 0xa10c040b, KEY_RECORD }, ++ { 0xa10c7807, KEY_CHANNELUP }, ++ { 0xa10cf807, KEY_CHANNELDOWN }, ++ { 0x0085301f, KEY_CHANNELDOWN }, ++ ++ { 0xa10c840b, KEY_PLAY }, ++ { 0xa10cc40b, KEY_PAUSE }, ++ { 0xa10ca40b, KEY_SLOW }, ++ { 0xa10c440b, KEY_REWIND }, ++ { 0xa10c240b, KEY_FASTFORWARD }, ++ { 0xa10c640b, KEY_PREVIOUS }, ++ { 0xa10ce40b, KEY_NEXT }, /* ->| */ ++ ++ { 0xa10c220d, KEY_ZOOM }, /* Aspect */ ++ { 0xa10c120d, KEY_STOP }, ++ { 0xa10c520d, KEY_DVD }, /* DVD Menu */ ++ ++ { 0xa10c140b, KEY_NUMERIC_1 }, ++ { 0xa10c940b, KEY_NUMERIC_2 }, ++ { 0xa10c540b, KEY_NUMERIC_3 }, ++ { 0xa10cd40b, KEY_NUMERIC_4 }, ++ { 0xa10c340b, KEY_NUMERIC_5 }, ++ { 0xa10cb40b, KEY_NUMERIC_6 }, ++ { 0xa10c740b, KEY_NUMERIC_7 }, ++ { 0xa10cf40b, KEY_NUMERIC_8 }, ++ { 0x0085302f, KEY_NUMERIC_8 }, ++ { 0xa10c0c03, KEY_NUMERIC_9 }, ++ { 0xa10c8c03, KEY_NUMERIC_0 }, ++ { 0xa10ccc03, KEY_ENTER }, ++ { 0xa10c4c03, KEY_CLEAR }, ++}; ++ ++static struct rc_map_list tivo_map = { ++ .map = { ++ .scan = tivo, ++ .size = ARRAY_SIZE(tivo), ++ .rc_type = RC_TYPE_NEC, ++ .name = RC_MAP_TIVO, ++ } ++}; ++ ++static int __init init_rc_map_tivo(void) ++{ ++ return rc_map_register(&tivo_map); ++} ++ ++static void __exit exit_rc_map_tivo(void) ++{ ++ rc_map_unregister(&tivo_map); ++} ++ ++module_init(init_rc_map_tivo) ++module_exit(exit_rc_map_tivo) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Jarod Wilson "); +diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c +index 044fb7a..47a1c5d 100644 +--- a/drivers/media/rc/mceusb.c ++++ b/drivers/media/rc/mceusb.c +@@ -149,6 +149,8 @@ enum mceusb_model_type { + POLARIS_EVK, + CX_HYBRID_TV, + MULTIFUNCTION, ++ TIVO_KIT, ++ MCE_GEN2_NO_TX, + }; + + struct mceusb_model { +@@ -172,6 +174,10 @@ static const struct mceusb_model mceusb_model[] = { + [MCE_GEN2] = { + .mce_gen2 = 1, + }, ++ [MCE_GEN2_NO_TX] = { ++ .mce_gen2 = 1, ++ .no_tx = 1, ++ }, + [MCE_GEN2_TX_INV] = { + .mce_gen2 = 1, + .tx_mask_normal = 1, +@@ -197,6 +203,10 @@ static const struct mceusb_model mceusb_model[] = { + .mce_gen2 = 1, + .ir_intfnum = 2, + }, ++ [TIVO_KIT] = { ++ .mce_gen2 = 1, ++ .rc_map = RC_MAP_TIVO, ++ }, + }; + + static struct usb_device_id mceusb_dev_table[] = { +@@ -277,7 +287,8 @@ static struct usb_device_id mceusb_dev_table[] = { + /* Formosa21 / eHome Infrared Receiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, + /* Formosa aim / Trust MCE Infrared Receiver */ +- { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, ++ { USB_DEVICE(VENDOR_FORMOSA, 0xe017), ++ .driver_info = MCE_GEN2_NO_TX }, + /* Formosa Industrial Computing / Beanbag Emulation Device */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, + /* Formosa21 / eHome Infrared Receiver */ +@@ -306,7 +317,8 @@ static struct usb_device_id mceusb_dev_table[] = { + /* Northstar Systems, Inc. eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, + /* TiVo PC IR Receiver */ +- { USB_DEVICE(VENDOR_TIVO, 0x2000) }, ++ { USB_DEVICE(VENDOR_TIVO, 0x2000), ++ .driver_info = TIVO_KIT }, + /* Conexant Hybrid TV "Shelby" Polaris SDK */ + { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), + .driver_info = POLARIS_EVK }, +diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c +index d4d6449..5d93384 100644 +--- a/drivers/media/rc/nuvoton-cir.c ++++ b/drivers/media/rc/nuvoton-cir.c +@@ -37,8 +37,6 @@ + + #include "nuvoton-cir.h" + +-static char *chip_id = "w836x7hg"; +- + /* write val to config reg */ + static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) + { +@@ -233,6 +231,8 @@ static int nvt_hw_detect(struct nvt_dev *nvt) + unsigned long flags; + u8 chip_major, chip_minor; + int ret = 0; ++ char chip_id[12]; ++ bool chip_unknown = false; + + nvt_efm_enable(nvt); + +@@ -246,15 +246,39 @@ static int nvt_hw_detect(struct nvt_dev *nvt) + } + + chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); +- nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); + +- if (chip_major != CHIP_ID_HIGH || +- (chip_minor != CHIP_ID_LOW && chip_minor != CHIP_ID_LOW2)) { +- nvt_pr(KERN_ERR, "%s: unsupported chip, id: 0x%02x 0x%02x", +- chip_id, chip_major, chip_minor); +- ret = -ENODEV; ++ /* these are the known working chip revisions... */ ++ switch (chip_major) { ++ case CHIP_ID_HIGH_667: ++ strcpy(chip_id, "w83667hg\0"); ++ if (chip_minor != CHIP_ID_LOW_667) ++ chip_unknown = true; ++ break; ++ case CHIP_ID_HIGH_677B: ++ strcpy(chip_id, "w83677hg\0"); ++ if (chip_minor != CHIP_ID_LOW_677B2 && ++ chip_minor != CHIP_ID_LOW_677B3) ++ chip_unknown = true; ++ break; ++ case CHIP_ID_HIGH_677C: ++ strcpy(chip_id, "w83677hg-c\0"); ++ if (chip_minor != CHIP_ID_LOW_677C) ++ chip_unknown = true; ++ break; ++ default: ++ strcpy(chip_id, "w836x7hg\0"); ++ chip_unknown = true; ++ break; + } + ++ /* warn, but still let the driver load, if we don't know this chip */ ++ if (chip_unknown) ++ nvt_pr(KERN_WARNING, "%s: unknown chip, id: 0x%02x 0x%02x, " ++ "it may not work...", chip_id, chip_major, chip_minor); ++ else ++ nvt_dbg("%s: chip id: 0x%02x 0x%02x", ++ chip_id, chip_major, chip_minor); ++ + nvt_efm_disable(nvt); + + spin_lock_irqsave(&nvt->nvt_lock, flags); +@@ -267,13 +291,23 @@ static int nvt_hw_detect(struct nvt_dev *nvt) + + static void nvt_cir_ldev_init(struct nvt_dev *nvt) + { +- u8 val; ++ u8 val, psreg, psmask, psval; ++ ++ if (nvt->chip_major == CHIP_ID_HIGH_667) { ++ psreg = CR_MULTIFUNC_PIN_SEL; ++ psmask = MULTIFUNC_PIN_SEL_MASK; ++ psval = MULTIFUNC_ENABLE_CIR | MULTIFUNC_ENABLE_CIRWB; ++ } else { ++ psreg = CR_OUTPUT_PIN_SEL; ++ psmask = OUTPUT_PIN_SEL_MASK; ++ psval = OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB; ++ } + +- /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ +- val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); +- val &= OUTPUT_PIN_SEL_MASK; +- val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); +- nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); ++ /* output pin selection: enable CIR, with WB sensor enabled */ ++ val = nvt_cr_read(nvt, psreg); ++ val &= psmask; ++ val |= psval; ++ nvt_cr_write(nvt, val, psreg); + + /* Select CIR logical device and enable */ + nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); +diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h +index 048135e..379795d 100644 +--- a/drivers/media/rc/nuvoton-cir.h ++++ b/drivers/media/rc/nuvoton-cir.h +@@ -330,9 +330,13 @@ struct nvt_dev { + #define EFER_EFM_DISABLE 0xaa + + /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ +-#define CHIP_ID_HIGH 0xb4 +-#define CHIP_ID_LOW 0x72 +-#define CHIP_ID_LOW2 0x73 ++#define CHIP_ID_HIGH_667 0xa5 ++#define CHIP_ID_HIGH_677B 0xb4 ++#define CHIP_ID_HIGH_677C 0xc3 ++#define CHIP_ID_LOW_667 0x13 ++#define CHIP_ID_LOW_677B2 0x72 ++#define CHIP_ID_LOW_677B3 0x73 ++#define CHIP_ID_LOW_677C 0x33 + + /* Config regs we need to care about */ + #define CR_SOFTWARE_RESET 0x02 +@@ -341,6 +345,7 @@ struct nvt_dev { + #define CR_CHIP_ID_LO 0x21 + #define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ + #define CR_OUTPUT_PIN_SEL 0x27 ++#define CR_MULTIFUNC_PIN_SEL 0x2c + #define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ + /* next three regs valid for both the CIR and CIR_WAKE logical devices */ + #define CR_CIR_BASE_ADDR_HI 0x60 +@@ -364,10 +369,16 @@ struct nvt_dev { + #define CIR_INTR_MOUSE_IRQ_BIT 0x80 + #define PME_INTR_CIR_PASS_BIT 0x08 + ++/* w83677hg CIR pin config */ + #define OUTPUT_PIN_SEL_MASK 0xbc + #define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ + #define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ + ++/* w83667hg CIR pin config */ ++#define MULTIFUNC_PIN_SEL_MASK 0x1f ++#define MULTIFUNC_ENABLE_CIR 0x80 /* Pin75=CIRRX, Pin76=CIRTX1 */ ++#define MULTIFUNC_ENABLE_CIRWB 0x20 /* enable wide-band sensor */ ++ + /* MCE CIR signal length, related on sample period */ + + /* MCE CIR controller signal length: about 43ms +diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c +index 63a438d..7080cde 100644 +--- a/drivers/staging/lirc/lirc_sasem.c ++++ b/drivers/staging/lirc/lirc_sasem.c +@@ -570,6 +570,7 @@ static void incoming_packet(struct sasem_context *context, + unsigned char *buf = urb->transfer_buffer; + long ms; + struct timeval tv; ++ int i; + + if (len != 8) { + printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n", +@@ -577,12 +578,12 @@ static void incoming_packet(struct sasem_context *context, + return; + } + +-#ifdef DEBUG +- int i; +- for (i = 0; i < 8; ++i) +- printk(KERN_INFO "%02x ", buf[i]); +- printk(KERN_INFO "\n"); +-#endif ++ if (debug) { ++ printk(KERN_INFO "Incoming data: "); ++ for (i = 0; i < 8; ++i) ++ printk(KERN_CONT "%02x ", buf[i]); ++ printk(KERN_CONT "\n"); ++ } + + /* + * Lirc could deal with the repeat code, but we really need to block it +diff --git a/include/linux/input.h b/include/linux/input.h +index e428382..be082e9 100644 +--- a/include/linux/input.h ++++ b/include/linux/input.h +@@ -553,8 +553,8 @@ struct input_keymap_entry { + #define KEY_DVD 0x185 /* Media Select DVD */ + #define KEY_AUX 0x186 + #define KEY_MP3 0x187 +-#define KEY_AUDIO 0x188 +-#define KEY_VIDEO 0x189 ++#define KEY_AUDIO 0x188 /* AL Audio Browser */ ++#define KEY_VIDEO 0x189 /* AL Movie Browser */ + #define KEY_DIRECTORY 0x18a + #define KEY_LIST 0x18b + #define KEY_MEMO 0x18c /* Media Select Messages */ +@@ -605,6 +605,7 @@ struct input_keymap_entry { + #define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ + #define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ + #define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ ++#define KEY_IMAGES 0x1ba /* AL Image Browser */ + + #define KEY_DEL_EOL 0x1c0 + #define KEY_DEL_EOS 0x1c1 +diff --git a/include/media/rc-map.h b/include/media/rc-map.h +index 9184751..b2bd405 100644 +--- a/include/media/rc-map.h ++++ b/include/media/rc-map.h +@@ -58,6 +58,7 @@ void rc_map_init(void); + #define RC_MAP_ALINK_DTU_M "rc-alink-dtu-m" + #define RC_MAP_ANYSEE "rc-anysee" + #define RC_MAP_APAC_VIEWCOMP "rc-apac-viewcomp" ++#define RC_MAP_APPLE "rc-apple" + #define RC_MAP_ASUS_PC39 "rc-asus-pc39" + #define RC_MAP_ATI_TV_WONDER_HD_600 "rc-ati-tv-wonder-hd-600" + #define RC_MAP_AVERMEDIA_A16D "rc-avermedia-a16d" +@@ -136,6 +137,7 @@ void rc_map_init(void); + #define RC_MAP_TERRATEC_CINERGY_XS "rc-terratec-cinergy-xs" + #define RC_MAP_TERRATEC_SLIM "rc-terratec-slim" + #define RC_MAP_TEVII_NEC "rc-tevii-nec" ++#define RC_MAP_TIVO "rc-tivo" + #define RC_MAP_TOTAL_MEDIA_IN_HAND "rc-total-media-in-hand" + #define RC_MAP_TREKSTOR "rc-trekstor" + #define RC_MAP_TT_1500 "rc-tt-1500" diff --git a/linux-2.6-v4l-dvb-ir-core-update.patch b/linux-2.6-v4l-dvb-ir-core-update.patch deleted file mode 100644 index c1105a330..000000000 --- a/linux-2.6-v4l-dvb-ir-core-update.patch +++ /dev/null @@ -1,6741 +0,0 @@ -Patch generated from the linuxtv staging/other branch, with a few -additional pending fixes merged in, and just about everything not -essential to the ir-core update chopped out. - -(Patch generated 2010.07.16) - -Signed-off-by: Jarod Wilson - ---- - Documentation/DocBook/media-entities.tmpl | 1 - Documentation/DocBook/media.tmpl | 8 - Documentation/DocBook/v4l/lirc_device_interface.xml | 235 ++++ - Documentation/DocBook/v4l/remote_controllers.xml | 2 - Documentation/dvb/get_dvb_firmware | 19 - Documentation/video4linux/CARDLIST.cx23885 | 6 - drivers/input/evdev.c | 39 - drivers/input/input.c | 268 ++++ - drivers/media/IR/Kconfig | 34 - drivers/media/IR/Makefile | 3 - drivers/media/IR/imon.c | 5 - drivers/media/IR/ir-core-priv.h | 54 - drivers/media/IR/ir-jvc-decoder.c | 152 -- - drivers/media/IR/ir-lirc-codec.c | 283 ++++ - drivers/media/IR/ir-nec-decoder.c | 151 -- - drivers/media/IR/ir-raw-event.c | 167 +- - drivers/media/IR/ir-rc5-decoder.c | 167 -- - drivers/media/IR/ir-rc6-decoder.c | 153 -- - drivers/media/IR/ir-sony-decoder.c | 155 -- - drivers/media/IR/ir-sysfs.c | 261 ++-- - drivers/media/IR/keymaps/Makefile | 2 - drivers/media/IR/keymaps/rc-lirc.c | 41 - drivers/media/IR/keymaps/rc-rc6-mce.c | 105 + - drivers/media/IR/lirc_dev.c | 764 +++++++++++++ - drivers/media/IR/mceusb.c | 1143 ++++++++++++++++++++ - drivers/media/common/tuners/tda18271-fe.c | 8 - drivers/media/dvb/mantis/Kconfig | 14 - drivers/media/dvb/mantis/mantis_input.c | 5 - drivers/media/video/cx23885/cx23885-cards.c | 40 - drivers/media/video/cx23885/cx23885-core.c | 11 - drivers/media/video/cx23885/cx23885-dvb.c | 2 - drivers/media/video/cx23885/cx23885-input.c | 317 +---- - drivers/media/video/cx23885/cx23885-ir.c | 2 - drivers/media/video/cx23885/cx23885.h | 12 - drivers/media/video/cx88/cx88-cards.c | 9 - drivers/media/video/cx88/cx88-i2c.c | 6 - drivers/media/video/cx88/cx88-input.c | 46 - drivers/media/video/cx88/cx88.h | 1 - drivers/media/video/em28xx/em28xx-input.c | 80 - - drivers/media/video/em28xx/em28xx-video.c | 4 - drivers/media/video/em28xx/em28xx.h | 1 - drivers/media/video/hdpvr/hdpvr-core.c | 5 - drivers/media/video/ir-kbd-i2c.c | 14 - drivers/media/video/pvrusb2/pvrusb2-ioread.c | 5 - include/linux/input.h | 39 - include/media/ir-core.h | 8 - include/media/ir-kbd-i2c.h | 2 - include/media/lirc.h | 165 ++ - include/media/lirc_dev.h | 225 +++ - include/media/rc-map.h | 7 - 50 files changed, 3971 insertions(+), 1275 deletions(-) - -diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl -index 5d4d40f..6ae9715 100644 ---- a/Documentation/DocBook/media-entities.tmpl -+++ b/Documentation/DocBook/media-entities.tmpl -@@ -218,6 +218,7 @@ - - - -+ - - - -diff --git a/Documentation/DocBook/media.tmpl b/Documentation/DocBook/media.tmpl -index eea564b..f11048d 100644 ---- a/Documentation/DocBook/media.tmpl -+++ b/Documentation/DocBook/media.tmpl -@@ -28,7 +28,7 @@ - LINUX MEDIA INFRASTRUCTURE API - - -- 2009 -+ 2009-2010 - LinuxTV Developers - - -@@ -61,7 +61,7 @@ Foundation. A copy of the license is included in the chapter entitled - in fact it covers several different video standards including - DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated - to documment support also for DVB-S2, ISDB-T and ISDB-S. -- The third part covers other API's used by all media infrastructure devices -+ The third part covers Remote Controller API - For additional information and for the latest development code, - see: http://linuxtv.org. - For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: Linux Media Mailing List (LMML).. -@@ -86,7 +86,7 @@ Foundation. A copy of the license is included in the chapter entitled - - - -- 2009 -+ 2009-2010 - Mauro Carvalho Chehab - - -@@ -101,7 +101,7 @@ Foundation. A copy of the license is included in the chapter entitled - - - --Other API's used by media infrastructure drivers -+Remote Controller API - - &sub-remote_controllers; - -diff --git a/Documentation/DocBook/v4l/lirc_device_interface.xml b/Documentation/DocBook/v4l/lirc_device_interface.xml -new file mode 100644 -index 0000000..0413234 ---- /dev/null -+++ b/Documentation/DocBook/v4l/lirc_device_interface.xml -@@ -0,0 +1,235 @@ -+
-+LIRC Device Interface -+ -+ -+
-+Introduction -+ -+The LIRC device interface is a bi-directional interface for -+transporting raw IR data between userspace and kernelspace. Fundamentally, -+it is just a chardev (/dev/lircX, for X = 0, 1, 2, ...), with a number -+of standard struct file_operations defined on it. With respect to -+transporting raw IR data to and fro, the essential fops are read, write -+and ioctl. -+ -+Example dmesg output upon a driver registering w/LIRC: -+
-+ $ dmesg |grep lirc_dev -+ lirc_dev: IR Remote Control driver registered, major 248 -+ rc rc0: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 0 -+
-+ -+What you should see for a chardev: -+
-+ $ ls -l /dev/lirc* -+ crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0 -+
-+
-+ -+
-+LIRC read fop -+ -+The lircd userspace daemon reads raw IR data from the LIRC chardev. The -+exact format of the data depends on what modes a driver supports, and what -+mode has been selected. lircd obtains supported modes and sets the active mode -+via the ioctl interface, detailed at . The generally -+preferred mode is LIRC_MODE_MODE2, in which packets containing an int value -+describing an IR signal are read from the chardev. -+ -+See also http://www.lirc.org/html/technical.html for more info. -+
-+ -+
-+LIRC write fop -+ -+The data written to the chardev is a pulse/space sequence of integer -+values. Pulses and spaces are only marked implicitly by their position. The -+data must start and end with a pulse, therefore, the data must always include -+an unevent number of samples. The write function must block until the data has -+been transmitted by the hardware. -+
-+ -+
-+LIRC ioctl fop -+ -+The LIRC device's ioctl definition is bound by the ioctl function -+definition of struct file_operations, leaving us with an unsigned int -+for the ioctl command and an unsigned long for the arg. For the purposes -+of ioctl portability across 32-bit and 64-bit, these values are capped -+to their 32-bit sizes. -+ -+The following ioctls can be used to change specific hardware settings. -+In general each driver should have a default set of settings. The driver -+implementation is expected to re-apply the default settings when the device -+is closed by user-space, so that every application opening the device can rely -+on working with the default settings initially. -+ -+ -+ -+ LIRC_GET_FEATURES -+ -+ Obviously, get the underlying hardware device's features. If a driver -+ does not announce support of certain features, calling of the corresponding -+ ioctls is undefined. -+ -+ -+ -+ LIRC_GET_SEND_MODE -+ -+ Get supported transmit mode. Only LIRC_MODE_PULSE is supported by lircd. -+ -+ -+ -+ LIRC_GET_REC_MODE -+ -+ Get supported receive modes. Only LIRC_MODE_MODE2 and LIRC_MODE_LIRCCODE -+ are supported by lircd. -+ -+ -+ -+ LIRC_GET_SEND_CARRIER -+ -+ Get carrier frequency (in Hz) currently used for transmit. -+ -+ -+ -+ LIRC_GET_REC_CARRIER -+ -+ Get carrier frequency (in Hz) currently used for IR reception. -+ -+ -+ -+ LIRC_{G,S}ET_{SEND,REC}_DUTY_CYCLE -+ -+ Get/set the duty cycle (from 0 to 100) of the carrier signal. Currently, -+ no special meaning is defined for 0 or 100, but this could be used to switch -+ off carrier generation in the future, so these values should be reserved. -+ -+ -+ -+ LIRC_GET_REC_RESOLUTION -+ -+ Some receiver have maximum resolution which is defined by internal -+ sample rate or data format limitations. E.g. it's common that signals can -+ only be reported in 50 microsecond steps. This integer value is used by -+ lircd to automatically adjust the aeps tolerance value in the lircd -+ config file. -+ -+ -+ -+ LIRC_GET_M{IN,AX}_TIMEOUT -+ -+ Some devices have internal timers that can be used to detect when -+ there's no IR activity for a long time. This can help lircd in detecting -+ that a IR signal is finished and can speed up the decoding process. -+ Returns an integer value with the minimum/maximum timeout that can be -+ set. Some devices have a fixed timeout, in that case both ioctls will -+ return the same value even though the timeout cannot be changed. -+ -+ -+ -+ LIRC_GET_M{IN,AX}_FILTER_{PULSE,SPACE} -+ -+ Some devices are able to filter out spikes in the incoming signal -+ using given filter rules. These ioctls return the hardware capabilities -+ that describe the bounds of the possible filters. Filter settings depend -+ on the IR protocols that are expected. lircd derives the settings from -+ all protocols definitions found in its config file. -+ -+ -+ -+ LIRC_GET_LENGTH -+ -+ Retrieves the code length in bits (only for LIRC_MODE_LIRCCODE). -+ Reads on the device must be done in blocks matching the bit count. -+ The bit could should be rounded up so that it matches full bytes. -+ -+ -+ -+ LIRC_SET_{SEND,REC}_MODE -+ -+ Set send/receive mode. Largely obsolete for send, as only -+ LIRC_MODE_PULSE is supported. -+ -+ -+ -+ LIRC_SET_{SEND,REC}_CARRIER -+ -+ Set send/receive carrier (in Hz). -+ -+ -+ -+ LIRC_SET_TRANSMITTER_MASK -+ -+ This enables the given set of transmitters. The first transmitter -+ is encoded by the least significant bit, etc. When an invalid bit mask -+ is given, i.e. a bit is set, even though the device does not have so many -+ transitters, then this ioctl returns the number of available transitters -+ and does nothing otherwise. -+ -+ -+ -+ LIRC_SET_REC_TIMEOUT -+ -+ Sets the integer value for IR inactivity timeout (cf. -+ LIRC_GET_MIN_TIMEOUT and LIRC_GET_MAX_TIMEOUT). A value of 0 (if -+ supported by the hardware) disables all hardware timeouts and data should -+ be reported as soon as possible. If the exact value cannot be set, then -+ the next possible value _greater_ than the given value should be set. -+ -+ -+ -+ LIRC_SET_REC_TIMEOUT_REPORTS -+ -+ Enable (1) or disable (0) timeout reports in LIRC_MODE_MODE2. By -+ default, timeout reports should be turned off. -+ -+ -+ -+ LIRC_SET_REC_FILTER_{,PULSE,SPACE} -+ -+ Pulses/spaces shorter than this are filtered out by hardware. If -+ filters cannot be set independently for pulse/space, the corresponding -+ ioctls must return an error and LIRC_SET_REC_FILTER shall be used instead. -+ -+ -+ -+ LIRC_SET_MEASURE_CARRIER_MODE -+ -+ Enable (1)/disable (0) measure mode. If enabled, from the next key -+ press on, the driver will send LIRC_MODE2_FREQUENCY packets. By default -+ this should be turned off. -+ -+ -+ -+ LIRC_SET_REC_{DUTY_CYCLE,CARRIER}_RANGE -+ -+ To set a range use LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE -+ with the lower bound first and later LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER -+ with the upper bound. -+ -+ -+ -+ LIRC_NOTIFY_DECODE -+ -+ This ioctl is called by lircd whenever a successful decoding of an -+ incoming IR signal could be done. This can be used by supporting hardware -+ to give visual feedback to the user e.g. by flashing a LED. -+ -+ -+ -+ LIRC_SETUP_{START,END} -+ -+ Setting of several driver parameters can be optimized by encapsulating -+ the according ioctl calls with LIRC_SETUP_START/LIRC_SETUP_END. When a -+ driver receives a LIRC_SETUP_START ioctl it can choose to not commit -+ further setting changes to the hardware until a LIRC_SETUP_END is received. -+ But this is open to the driver implementation and every driver must also -+ handle parameter changes which are not encapsulated by LIRC_SETUP_START -+ and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls. -+ -+ -+ -+ -+
-+
-diff --git a/Documentation/DocBook/v4l/remote_controllers.xml b/Documentation/DocBook/v4l/remote_controllers.xml -index 73f5eab..3c3b667 100644 ---- a/Documentation/DocBook/v4l/remote_controllers.xml -+++ b/Documentation/DocBook/v4l/remote_controllers.xml -@@ -173,3 +173,5 @@ keymapping. - This program demonstrates how to replace the keymap tables. - &sub-keytable-c; - -+ -+&sub-lirc_device_interface; -diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware -index 239cbdb..9ea94dc 100644 ---- a/Documentation/dvb/get_dvb_firmware -+++ b/Documentation/dvb/get_dvb_firmware -@@ -26,7 +26,7 @@ use IO::Handle; - "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", - "or51211", "or51132_qam", "or51132_vsb", "bluebird", - "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718", -- "af9015", "ngene"); -+ "af9015", "ngene", "az6027"); - - # Check args - syntax() if (scalar(@ARGV) != 1); -@@ -567,6 +567,23 @@ sub ngene { - "$file1, $file2"; - } - -+sub az6027{ -+ my $file = "AZ6027_Linux_Driver.tar.gz"; -+ my $url = "http://linux.terratec.de/files/$file"; -+ my $firmware = "dvb-usb-az6027-03.fw"; -+ -+ wgetfile($file, $url); -+ -+ #untar -+ if( system("tar xzvf $file $firmware")){ -+ die "failed to untar firmware"; -+ } -+ if( system("rm $file")){ -+ die ("unable to remove unnecessary files"); -+ } -+ -+ $firmware; -+} - # --------------------------------------------------------------- - # Utilities - -diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 -index 16ca030..87c4634 100644 ---- a/Documentation/video4linux/CARDLIST.cx23885 -+++ b/Documentation/video4linux/CARDLIST.cx23885 -@@ -17,9 +17,9 @@ - 16 -> DVBWorld DVB-S2 2005 [0001:2005] - 17 -> NetUP Dual DVB-S2 CI [1b55:2a2c] - 18 -> Hauppauge WinTV-HVR1270 [0070:2211] -- 19 -> Hauppauge WinTV-HVR1275 [0070:2215] -- 20 -> Hauppauge WinTV-HVR1255 [0070:2251] -- 21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295] -+ 19 -> Hauppauge WinTV-HVR1275 [0070:2215,0070:221d,0070:22f2] -+ 20 -> Hauppauge WinTV-HVR1255 [0070:2251,0070:2259,0070:22f1] -+ 21 -> Hauppauge WinTV-HVR1210 [0070:2291,0070:2295,0070:2299,0070:229d,0070:22f0,0070:22f3,0070:22f4,0070:22f5] - 22 -> Mygica X8506 DMB-TH [14f1:8651] - 23 -> Magic-Pro ProHDTV Extreme 2 [14f1:8657] - 24 -> Hauppauge WinTV-HVR1850 [0070:8541] -diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl -old mode 100644 -new mode 100755 -diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c -index 2ee6c7a..b8a5673 100644 ---- a/drivers/input/evdev.c -+++ b/drivers/input/evdev.c -@@ -515,6 +515,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, - struct input_absinfo abs; - struct ff_effect effect; - int __user *ip = (int __user *)p; -+ struct keycode_table_entry kt, *kt_p = p; -+ char scancode[16]; - unsigned int i, t, u, v; - int error; - -@@ -569,6 +571,43 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, - - return input_set_keycode(dev, t, v); - -+ case EVIOCGKEYCODEBIG: -+ if (copy_from_user(&kt, kt_p, sizeof(kt))) -+ return -EFAULT; -+ -+ if (kt.len > sizeof(scancode)) -+ return -EINVAL; -+ -+ kt.scancode = scancode; -+ -+ error = input_get_keycode_big(dev, &kt); -+ if (error) -+ return error; -+ -+ if (copy_to_user(kt_p, &kt, sizeof(kt))) -+ return -EFAULT; -+ -+ /* FIXME: probably need some compat32 code */ -+ if (copy_to_user(kt_p->scancode, kt.scancode, kt.len)) -+ return -EFAULT; -+ -+ return 0; -+ -+ case EVIOCSKEYCODEBIG: -+ if (copy_from_user(&kt, kt_p, sizeof(kt))) -+ return -EFAULT; -+ -+ if (kt.len > sizeof(scancode)) -+ return -EINVAL; -+ -+ kt.scancode = scancode; -+ -+ /* FIXME: probably need some compat32 code */ -+ if (copy_from_user(kt.scancode, kt_p->scancode, kt.len)) -+ return -EFAULT; -+ -+ return input_set_keycode_big(dev, &kt); -+ - case EVIOCRMFF: - return input_ff_erase(dev, (int)(unsigned long) p, file); - -diff --git a/drivers/input/input.c b/drivers/input/input.c -index 9c79bd5..43aeb71 100644 ---- a/drivers/input/input.c -+++ b/drivers/input/input.c -@@ -568,6 +568,11 @@ static void input_disconnect_device(struct input_dev *dev) - spin_unlock_irq(&dev->event_lock); - } - -+/* -+ * Those routines handle the default case where no [gs]etkeycode() is -+ * defined. In this case, an array indexed by the scancode is used. -+ */ -+ - static int input_fetch_keycode(struct input_dev *dev, int scancode) - { - switch (dev->keycodesize) { -@@ -582,27 +587,74 @@ static int input_fetch_keycode(struct input_dev *dev, int scancode) - } - } - --static int input_default_getkeycode(struct input_dev *dev, -- unsigned int scancode, -- unsigned int *keycode) -+/* -+ * Supports only 8, 16 and 32 bit scancodes. It wouldn't be that -+ * hard to write some machine-endian logic to support 24 bit scancodes, -+ * but it seemed overkill. It should also be noticed that, since there -+ * are, in general, less than 256 scancodes sparsed into the scancode -+ * space, even with 16 bits, the codespace is sparsed, with leads into -+ * memory and code ineficiency, when retrieving the entire scancode -+ * space. -+ * So, it is highly recommended to implement getkeycodebig/setkeycodebig -+ * instead of using a normal table approach, when more than 8 bits is -+ * needed for the scancode. -+ */ -+static int input_fetch_scancode(struct keycode_table_entry *kt_entry, -+ u32 *scancode) - { -+ switch (kt_entry->len) { -+ case 1: -+ *scancode = *((u8 *)kt_entry->scancode); -+ break; -+ case 2: -+ *scancode = *((u16 *)kt_entry->scancode); -+ break; -+ case 4: -+ *scancode = *((u32 *)kt_entry->scancode); -+ break; -+ default: -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+ -+static int input_default_getkeycode_from_index(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry) -+{ -+ u32 scancode = kt_entry->index; -+ - if (!dev->keycodesize) - return -EINVAL; - - if (scancode >= dev->keycodemax) - return -EINVAL; - -- *keycode = input_fetch_keycode(dev, scancode); -+ kt_entry->keycode = input_fetch_keycode(dev, scancode); -+ memcpy(kt_entry->scancode, &scancode, 4); - - return 0; - } - -+static int input_default_getkeycode_from_scancode(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry) -+{ -+ if (input_fetch_scancode(kt_entry, &kt_entry->index)) -+ return -EINVAL; -+ -+ return input_default_getkeycode_from_index(dev, kt_entry); -+} -+ -+ - static int input_default_setkeycode(struct input_dev *dev, -- unsigned int scancode, -- unsigned int keycode) -+ struct keycode_table_entry *kt_entry) - { -- int old_keycode; -+ u32 old_keycode; - int i; -+ u32 scancode; -+ -+ if (input_fetch_scancode(kt_entry, &scancode)) -+ return -EINVAL; - - if (scancode >= dev->keycodemax) - return -EINVAL; -@@ -610,32 +662,33 @@ static int input_default_setkeycode(struct input_dev *dev, - if (!dev->keycodesize) - return -EINVAL; - -- if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) -+ if (dev->keycodesize < sizeof(dev->keycode) && -+ (kt_entry->keycode >> (dev->keycodesize * 8))) - return -EINVAL; - - switch (dev->keycodesize) { - case 1: { - u8 *k = (u8 *)dev->keycode; - old_keycode = k[scancode]; -- k[scancode] = keycode; -+ k[scancode] = kt_entry->keycode; - break; - } - case 2: { - u16 *k = (u16 *)dev->keycode; - old_keycode = k[scancode]; -- k[scancode] = keycode; -+ k[scancode] = kt_entry->keycode; - break; - } - default: { - u32 *k = (u32 *)dev->keycode; - old_keycode = k[scancode]; -- k[scancode] = keycode; -+ k[scancode] = kt_entry->keycode; - break; - } - } - - __clear_bit(old_keycode, dev->keybit); -- __set_bit(keycode, dev->keybit); -+ __set_bit(kt_entry->keycode, dev->keybit); - - for (i = 0; i < dev->keycodemax; i++) { - if (input_fetch_keycode(dev, i) == old_keycode) { -@@ -648,6 +701,110 @@ static int input_default_setkeycode(struct input_dev *dev, - } - - /** -+ * input_get_keycode_big - retrieve keycode currently mapped to a given scancode -+ * @dev: input device which keymap is being queried -+ * @kt_entry: keytable entry -+ * -+ * This function should be called by anyone interested in retrieving current -+ * keymap. Presently evdev handlers use it. -+ */ -+int input_get_keycode_big(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry) -+{ -+ if (dev->getkeycode) { -+ u32 scancode = kt_entry->index; -+ -+ /* -+ * Support for legacy drivers, that don't implement the new -+ * ioctls -+ */ -+ memcpy(kt_entry->scancode, &scancode, 4); -+ return dev->getkeycode(dev, scancode, -+ &kt_entry->keycode); -+ } else -+ return dev->getkeycodebig_from_index(dev, kt_entry); -+} -+EXPORT_SYMBOL(input_get_keycode_big); -+ -+/** -+ * input_set_keycode_big - attribute a keycode to a given scancode -+ * @dev: input device which keymap is being queried -+ * @kt_entry: keytable entry -+ * -+ * This function should be called by anyone needing to update current -+ * keymap. Presently keyboard and evdev handlers use it. -+ */ -+int input_set_keycode_big(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry) -+{ -+ unsigned long flags; -+ int old_keycode; -+ int retval = -EINVAL; -+ u32 uninitialized_var(scancode); -+ -+ if (kt_entry->keycode < 0 || kt_entry->keycode > KEY_MAX) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ -+ /* -+ * We need to know the old scancode, in order to generate a -+ * keyup effect, if the set operation happens successfully -+ */ -+ if (dev->getkeycode) { -+ /* -+ * Support for legacy drivers, that don't implement the new -+ * ioctls -+ */ -+ if (!dev->setkeycode) -+ goto out; -+ -+ retval = input_fetch_scancode(kt_entry, &scancode); -+ if (retval) -+ goto out; -+ -+ retval = dev->getkeycode(dev, scancode, -+ &old_keycode); -+ } else { -+ int new_keycode = kt_entry->keycode; -+ -+ retval = dev->getkeycodebig_from_scancode(dev, kt_entry); -+ old_keycode = kt_entry->keycode; -+ kt_entry->keycode = new_keycode; -+ } -+ -+ if (retval) -+ goto out; -+ -+ if (dev->getkeycode) -+ retval = dev->setkeycode(dev, scancode, -+ kt_entry->keycode); -+ else -+ retval = dev->setkeycodebig(dev, kt_entry); -+ if (retval) -+ goto out; -+ -+ /* -+ * Simulate keyup event if keycode is not present -+ * in the keymap anymore -+ */ -+ if (test_bit(EV_KEY, dev->evbit) && -+ !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && -+ __test_and_clear_bit(old_keycode, dev->key)) { -+ -+ input_pass_event(dev, EV_KEY, old_keycode, 0); -+ if (dev->sync) -+ input_pass_event(dev, EV_SYN, SYN_REPORT, 1); -+ } -+ -+ out: -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ -+ return retval; -+} -+EXPORT_SYMBOL(input_set_keycode_big); -+ -+/** - * input_get_keycode - retrieve keycode currently mapped to a given scancode - * @dev: input device which keymap is being queried - * @scancode: scancode (or its equivalent for device in question) for which -@@ -661,13 +818,35 @@ int input_get_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode) - { - unsigned long flags; -- int retval; - -- spin_lock_irqsave(&dev->event_lock, flags); -- retval = dev->getkeycode(dev, scancode, keycode); -- spin_unlock_irqrestore(&dev->event_lock, flags); -+ if (dev->getkeycode) { -+ /* -+ * Use the legacy calls -+ */ -+ return dev->getkeycode(dev, scancode, keycode); -+ } else { -+ int retval; -+ struct keycode_table_entry kt_entry; - -- return retval; -+ /* -+ * Userspace is using a legacy call with a driver ported -+ * to the new way. This is a bad idea with long sparsed -+ * tables, since lots of the retrieved values will be in -+ * blank. Also, it makes sense only if the table size is -+ * lower than 2^32. -+ */ -+ memset(&kt_entry, 0, sizeof(kt_entry)); -+ kt_entry.len = 4; -+ kt_entry.index = scancode; -+ kt_entry.scancode = (char *)&scancode; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ retval = dev->getkeycodebig_from_index(dev, &kt_entry); -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ -+ *keycode = kt_entry.keycode; -+ return retval; -+ } - } - EXPORT_SYMBOL(input_get_keycode); - -@@ -692,13 +871,42 @@ int input_set_keycode(struct input_dev *dev, - - spin_lock_irqsave(&dev->event_lock, flags); - -- retval = dev->getkeycode(dev, scancode, &old_keycode); -- if (retval) -- goto out; -+ if (dev->getkeycode) { -+ /* -+ * Use the legacy calls -+ */ -+ retval = dev->getkeycode(dev, scancode, &old_keycode); -+ if (retval) -+ goto out; - -- retval = dev->setkeycode(dev, scancode, keycode); -- if (retval) -- goto out; -+ retval = dev->setkeycode(dev, scancode, keycode); -+ if (retval) -+ goto out; -+ } else { -+ struct keycode_table_entry kt_entry; -+ -+ /* -+ * Userspace is using a legacy call with a driver ported -+ * to the new way. This is a bad idea with long sparsed -+ * tables, since lots of the retrieved values will be in -+ * blank. Also, it makes sense only if the table size is -+ * lower than 2^32. -+ */ -+ memset(&kt_entry, 0, sizeof(kt_entry)); -+ kt_entry.len = 4; -+ kt_entry.scancode = (char *)&scancode; -+ -+ retval = dev->getkeycodebig_from_scancode(dev, &kt_entry); -+ if (retval) -+ goto out; -+ -+ old_keycode = kt_entry.keycode; -+ kt_entry.keycode = keycode; -+ -+ retval = dev->setkeycodebig(dev, &kt_entry); -+ if (retval) -+ goto out; -+ } - - /* Make sure KEY_RESERVED did not get enabled. */ - __clear_bit(KEY_RESERVED, dev->keybit); -@@ -1636,11 +1843,17 @@ int input_register_device(struct input_dev *dev) - dev->rep[REP_PERIOD] = 33; - } - -- if (!dev->getkeycode) -- dev->getkeycode = input_default_getkeycode; -+ if (!dev->getkeycode) { -+ if (!dev->getkeycodebig_from_index) -+ dev->getkeycodebig_from_index = input_default_getkeycode_from_index; -+ if (!dev->getkeycodebig_from_scancode) -+ dev->getkeycodebig_from_scancode = input_default_getkeycode_from_scancode; -+ } - -- if (!dev->setkeycode) -- dev->setkeycode = input_default_setkeycode; -+ if (!dev->setkeycode) { -+ if (!dev->setkeycodebig) -+ dev->setkeycodebig = input_default_setkeycode; -+ } - - dev_set_name(&dev->dev, "input%ld", - (unsigned long) atomic_inc_return(&input_no) - 1); -diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig -index d22a8ec..e557ae0 100644 ---- a/drivers/media/IR/Kconfig -+++ b/drivers/media/IR/Kconfig -@@ -8,6 +8,17 @@ config VIDEO_IR - depends on IR_CORE - default IR_CORE - -+config LIRC -+ tristate -+ default y -+ -+ ---help--- -+ Enable this option to build the Linux Infrared Remote -+ Control (LIRC) core device interface driver. The LIRC -+ interface passes raw IR to and from userspace, where the -+ LIRC daemon handles protocol decoding for IR reception ann -+ encoding for IR transmitting (aka "blasting"). -+ - source "drivers/media/IR/keymaps/Kconfig" - - config IR_NEC_DECODER -@@ -42,6 +53,7 @@ config IR_RC6_DECODER - config IR_JVC_DECODER - tristate "Enable IR raw decoder for the JVC protocol" - depends on IR_CORE -+ select BITREVERSE - default y - - ---help--- -@@ -57,6 +69,16 @@ config IR_SONY_DECODER - Enable this option if you have an infrared remote control which - uses the Sony protocol, and you need software decoding support. - -+config IR_LIRC_CODEC -+ tristate "Enable IR to LIRC bridge" -+ depends on IR_CORE -+ depends on LIRC -+ default y -+ -+ ---help--- -+ Enable this option to pass raw IR to and from userspace via -+ the LIRC interface. -+ - config IR_IMON - tristate "SoundGraph iMON Receiver and Display" - depends on USB_ARCH_HAS_HCD -@@ -68,3 +90,15 @@ config IR_IMON - - To compile this driver as a module, choose M here: the - module will be called imon. -+ -+config IR_MCEUSB -+ tristate "Windows Media Center Ed. eHome Infrared Transceiver" -+ depends on USB_ARCH_HAS_HCD -+ depends on IR_CORE -+ select USB -+ ---help--- -+ Say Y here if you want to use a Windows Media Center Edition -+ eHome Infrared Transceiver. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called mceusb. -diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile -index b998fcc..2ae4f3a 100644 ---- a/drivers/media/IR/Makefile -+++ b/drivers/media/IR/Makefile -@@ -5,11 +5,14 @@ obj-y += keymaps/ - - obj-$(CONFIG_IR_CORE) += ir-core.o - obj-$(CONFIG_VIDEO_IR) += ir-common.o -+obj-$(CONFIG_LIRC) += lirc_dev.o - obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o - obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o - obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o - obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o - obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o -+obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o - - # stand-alone IR receivers/transmitters - obj-$(CONFIG_IR_IMON) += imon.o -+obj-$(CONFIG_IR_MCEUSB) += mceusb.o -diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c -index 4bbd45f..0195dd5 100644 ---- a/drivers/media/IR/imon.c -+++ b/drivers/media/IR/imon.c -@@ -1943,7 +1943,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) - return ictx; - - urb_submit_failed: -- input_unregister_device(ictx->idev); -+ ir_input_unregister(ictx->idev); - input_free_device(ictx->idev); - idev_setup_failed: - find_endpoint_failed: -@@ -2067,6 +2067,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx) - detected_display_type = IMON_DISPLAY_TYPE_VFD; - break; - /* iMON LCD, MCE IR */ -+ case 0x9e: - case 0x9f: - dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); - detected_display_type = IMON_DISPLAY_TYPE_LCD; -@@ -2306,7 +2307,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface) - if (ifnum == 0) { - ictx->dev_present_intf0 = false; - usb_kill_urb(ictx->rx_urb_intf0); -- input_unregister_device(ictx->idev); -+ ir_input_unregister(ictx->idev); - if (ictx->display_supported) { - if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) - usb_deregister_dev(interface, &imon_lcd_class); -diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h -index 9a5e65a..babd520 100644 ---- a/drivers/media/IR/ir-core-priv.h -+++ b/drivers/media/IR/ir-core-priv.h -@@ -22,17 +22,62 @@ - struct ir_raw_handler { - struct list_head list; - -+ u64 protocols; /* which are handled by this handler */ - int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); -+ -+ /* These two should only be used by the lirc decoder */ - int (*raw_register)(struct input_dev *input_dev); - int (*raw_unregister)(struct input_dev *input_dev); - }; - - struct ir_raw_event_ctrl { -+ struct list_head list; /* to keep track of raw clients */ - struct work_struct rx_work; /* for the rx decoding workqueue */ - struct kfifo kfifo; /* fifo for the pulse/space durations */ - ktime_t last_event; /* when last event occurred */ - enum raw_event_type last_type; /* last event type */ - struct input_dev *input_dev; /* pointer to the parent input_dev */ -+ u64 enabled_protocols; /* enabled raw protocol decoders */ -+ -+ /* raw decoder state follows */ -+ struct ir_raw_event prev_ev; -+ struct nec_dec { -+ int state; -+ unsigned count; -+ u32 bits; -+ } nec; -+ struct rc5_dec { -+ int state; -+ u32 bits; -+ unsigned count; -+ unsigned wanted_bits; -+ } rc5; -+ struct rc6_dec { -+ int state; -+ u8 header; -+ u32 body; -+ bool toggle; -+ unsigned count; -+ unsigned wanted_bits; -+ } rc6; -+ struct sony_dec { -+ int state; -+ u32 bits; -+ unsigned count; -+ } sony; -+ struct jvc_dec { -+ int state; -+ u16 bits; -+ u16 old_bits; -+ unsigned count; -+ bool first; -+ bool toggle; -+ } jvc; -+ struct lirc_codec { -+ struct ir_input_dev *ir_dev; -+ struct lirc_driver *drv; -+ int lircdata; -+ } lirc; - }; - - /* macros for IR decoders */ -@@ -74,6 +119,7 @@ void ir_unregister_class(struct input_dev *input_dev); - /* - * Routines from ir-raw-event.c to be used internally and by decoders - */ -+u64 ir_raw_get_allowed_protocols(void); - int ir_raw_event_register(struct input_dev *input_dev); - void ir_raw_event_unregister(struct input_dev *input_dev); - int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); -@@ -123,4 +169,12 @@ void ir_raw_init(void); - #define load_sony_decode() 0 - #endif - -+/* from ir-lirc-codec.c */ -+#ifdef CONFIG_IR_LIRC_CODEC_MODULE -+#define load_lirc_codec() request_module("ir-lirc-codec") -+#else -+#define load_lirc_codec() 0 -+#endif -+ -+ - #endif /* _IR_RAW_EVENT */ -diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c -index 0b80494..8894d8b 100644 ---- a/drivers/media/IR/ir-jvc-decoder.c -+++ b/drivers/media/IR/ir-jvc-decoder.c -@@ -25,10 +25,6 @@ - #define JVC_TRAILER_PULSE (1 * JVC_UNIT) - #define JVC_TRAILER_SPACE (35 * JVC_UNIT) - --/* Used to register jvc_decoder clients */ --static LIST_HEAD(decoder_list); --DEFINE_SPINLOCK(decoder_lock); -- - enum jvc_state { - STATE_INACTIVE, - STATE_HEADER_SPACE, -@@ -38,87 +34,6 @@ enum jvc_state { - STATE_TRAILER_SPACE, - }; - --struct decoder_data { -- struct list_head list; -- struct ir_input_dev *ir_dev; -- int enabled:1; -- -- /* State machine control */ -- enum jvc_state state; -- u16 jvc_bits; -- u16 jvc_old_bits; -- unsigned count; -- bool first; -- bool toggle; --}; -- -- --/** -- * get_decoder_data() - gets decoder data -- * @input_dev: input device -- * -- * Returns the struct decoder_data that corresponds to a device -- */ --static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) --{ -- struct decoder_data *data = NULL; -- -- spin_lock(&decoder_lock); -- list_for_each_entry(data, &decoder_list, list) { -- if (data->ir_dev == ir_dev) -- break; -- } -- spin_unlock(&decoder_lock); -- return data; --} -- --static ssize_t store_enabled(struct device *d, -- struct device_attribute *mattr, -- const char *buf, -- size_t len) --{ -- unsigned long value; -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (strict_strtoul(buf, 10, &value) || value > 1) -- return -EINVAL; -- -- data->enabled = value; -- -- return len; --} -- --static ssize_t show_enabled(struct device *d, -- struct device_attribute *mattr, char *buf) --{ -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (data->enabled) -- return sprintf(buf, "1\n"); -- else -- return sprintf(buf, "0\n"); --} -- --static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); -- --static struct attribute *decoder_attributes[] = { -- &dev_attr_enabled.attr, -- NULL --}; -- --static struct attribute_group decoder_attribute_group = { -- .name = "jvc_decoder", -- .attrs = decoder_attributes, --}; -- - /** - * ir_jvc_decode() - Decode one JVC pulse or space - * @input_dev: the struct input_dev descriptor of the device -@@ -128,14 +43,10 @@ static struct attribute_group decoder_attribute_group = { - */ - static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) - { -- struct decoder_data *data; - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ struct jvc_dec *data = &ir_dev->raw->jvc; - -- data = get_decoder_data(ir_dev); -- if (!data) -- return -EINVAL; -- -- if (!data->enabled) -+ if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC)) - return 0; - - if (IS_RESET(ev)) { -@@ -188,9 +99,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) - if (ev.pulse) - break; - -- data->jvc_bits <<= 1; -+ data->bits <<= 1; - if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) { -- data->jvc_bits |= 1; -+ data->bits |= 1; - decrease_duration(&ev, JVC_BIT_1_SPACE); - } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2)) - decrease_duration(&ev, JVC_BIT_0_SPACE); -@@ -223,13 +134,13 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) - - if (data->first) { - u32 scancode; -- scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) | -- (bitrev8((data->jvc_bits >> 0) & 0xff) << 0); -+ scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) | -+ (bitrev8((data->bits >> 0) & 0xff) << 0); - IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); - ir_keydown(input_dev, scancode, data->toggle); - data->first = false; -- data->jvc_old_bits = data->jvc_bits; -- } else if (data->jvc_bits == data->jvc_old_bits) { -+ data->old_bits = data->bits; -+ } else if (data->bits == data->old_bits) { - IR_dprintk(1, "JVC repeat\n"); - ir_repeat(input_dev); - } else { -@@ -249,54 +160,9 @@ out: - return -EINVAL; - } - --static int ir_jvc_register(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- struct decoder_data *data; -- int rc; -- -- rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- if (rc < 0) -- return rc; -- -- data = kzalloc(sizeof(*data), GFP_KERNEL); -- if (!data) { -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- return -ENOMEM; -- } -- -- data->ir_dev = ir_dev; -- data->enabled = 1; -- -- spin_lock(&decoder_lock); -- list_add_tail(&data->list, &decoder_list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- --static int ir_jvc_unregister(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- static struct decoder_data *data; -- -- data = get_decoder_data(ir_dev); -- if (!data) -- return 0; -- -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- -- spin_lock(&decoder_lock); -- list_del(&data->list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- - static struct ir_raw_handler jvc_handler = { -+ .protocols = IR_TYPE_JVC, - .decode = ir_jvc_decode, -- .raw_register = ir_jvc_register, -- .raw_unregister = ir_jvc_unregister, - }; - - static int __init ir_jvc_decode_init(void) -diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c -new file mode 100644 -index 0000000..afb1ada ---- /dev/null -+++ b/drivers/media/IR/ir-lirc-codec.c -@@ -0,0 +1,283 @@ -+/* ir-lirc-codec.c - ir-core to classic lirc interface bridge -+ * -+ * Copyright (C) 2010 by Jarod Wilson -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation version 2 of the License. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "ir-core-priv.h" -+ -+#define LIRCBUF_SIZE 256 -+ -+/** -+ * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the -+ * lircd userspace daemon for decoding. -+ * @input_dev: the struct input_dev descriptor of the device -+ * @duration: the struct ir_raw_event descriptor of the pulse/space -+ * -+ * This function returns -EINVAL if the lirc interfaces aren't wired up. -+ */ -+static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) -+{ -+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ -+ if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) -+ return 0; -+ -+ if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) -+ return -EINVAL; -+ -+ IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", -+ TO_US(ev.duration), TO_STR(ev.pulse)); -+ -+ ir_dev->raw->lirc.lircdata += ev.duration / 1000; -+ if (ev.pulse) -+ ir_dev->raw->lirc.lircdata |= PULSE_BIT; -+ -+ lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, -+ (unsigned char *) &ir_dev->raw->lirc.lircdata); -+ wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); -+ -+ ir_dev->raw->lirc.lircdata = 0; -+ -+ return 0; -+} -+ -+static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, -+ size_t n, loff_t *ppos) -+{ -+ struct lirc_codec *lirc; -+ struct ir_input_dev *ir_dev; -+ int *txbuf; /* buffer with values to transmit */ -+ int ret = 0, count; -+ -+ lirc = lirc_get_pdata(file); -+ if (!lirc) -+ return -EFAULT; -+ -+ if (n % sizeof(int)) -+ return -EINVAL; -+ -+ count = n / sizeof(int); -+ if (count > LIRCBUF_SIZE || count % 2 == 0) -+ return -EINVAL; -+ -+ txbuf = kzalloc(sizeof(int) * LIRCBUF_SIZE, GFP_KERNEL); -+ if (!txbuf) -+ return -ENOMEM; -+ -+ if (copy_from_user(txbuf, buf, n)) { -+ ret = -EFAULT; -+ goto out; -+ } -+ -+ ir_dev = lirc->ir_dev; -+ if (!ir_dev) { -+ ret = -EFAULT; -+ goto out; -+ } -+ -+ if (ir_dev->props && ir_dev->props->tx_ir) -+ ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n); -+ -+out: -+ kfree(txbuf); -+ return ret; -+} -+ -+static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) -+{ -+ struct lirc_codec *lirc; -+ struct ir_input_dev *ir_dev; -+ int ret = 0; -+ void *drv_data; -+ unsigned long val; -+ -+ lirc = lirc_get_pdata(filep); -+ if (!lirc) -+ return -EFAULT; -+ -+ ir_dev = lirc->ir_dev; -+ if (!ir_dev || !ir_dev->props || !ir_dev->props->priv) -+ return -EFAULT; -+ -+ drv_data = ir_dev->props->priv; -+ -+ switch (cmd) { -+ case LIRC_SET_TRANSMITTER_MASK: -+ ret = get_user(val, (unsigned long *)arg); -+ if (ret) -+ return ret; -+ -+ if (ir_dev->props && ir_dev->props->s_tx_mask) -+ ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); -+ else -+ return -EINVAL; -+ break; -+ -+ case LIRC_SET_SEND_CARRIER: -+ ret = get_user(val, (unsigned long *)arg); -+ if (ret) -+ return ret; -+ -+ if (ir_dev->props && ir_dev->props->s_tx_carrier) -+ ir_dev->props->s_tx_carrier(drv_data, (u32)val); -+ else -+ return -EINVAL; -+ break; -+ -+ case LIRC_GET_SEND_MODE: -+ val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; -+ ret = put_user(val, (unsigned long *)arg); -+ break; -+ -+ case LIRC_SET_SEND_MODE: -+ ret = get_user(val, (unsigned long *)arg); -+ if (ret) -+ return ret; -+ -+ if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) -+ return -EINVAL; -+ break; -+ -+ default: -+ return lirc_dev_fop_ioctl(filep, cmd, arg); -+ } -+ -+ return ret; -+} -+ -+static int ir_lirc_open(void *data) -+{ -+ return 0; -+} -+ -+static void ir_lirc_close(void *data) -+{ -+ return; -+} -+ -+static struct file_operations lirc_fops = { -+ .owner = THIS_MODULE, -+ .write = ir_lirc_transmit_ir, -+ .unlocked_ioctl = ir_lirc_ioctl, -+ .read = lirc_dev_fop_read, -+ .poll = lirc_dev_fop_poll, -+ .open = lirc_dev_fop_open, -+ .release = lirc_dev_fop_close, -+}; -+ -+static int ir_lirc_register(struct input_dev *input_dev) -+{ -+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ struct lirc_driver *drv; -+ struct lirc_buffer *rbuf; -+ int rc = -ENOMEM; -+ unsigned long features; -+ -+ drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); -+ if (!drv) -+ return rc; -+ -+ rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); -+ if (!drv) -+ goto rbuf_alloc_failed; -+ -+ rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE); -+ if (rc) -+ goto rbuf_init_failed; -+ -+ features = LIRC_CAN_REC_MODE2; -+ if (ir_dev->props->tx_ir) { -+ features |= LIRC_CAN_SEND_PULSE; -+ if (ir_dev->props->s_tx_mask) -+ features |= LIRC_CAN_SET_TRANSMITTER_MASK; -+ if (ir_dev->props->s_tx_carrier) -+ features |= LIRC_CAN_SET_SEND_CARRIER; -+ } -+ -+ snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", -+ ir_dev->driver_name); -+ drv->minor = -1; -+ drv->features = features; -+ drv->data = &ir_dev->raw->lirc; -+ drv->rbuf = rbuf; -+ drv->set_use_inc = &ir_lirc_open; -+ drv->set_use_dec = &ir_lirc_close; -+ drv->code_length = sizeof(struct ir_raw_event) * 8; -+ drv->fops = &lirc_fops; -+ drv->dev = &ir_dev->dev; -+ drv->owner = THIS_MODULE; -+ -+ drv->minor = lirc_register_driver(drv); -+ if (drv->minor < 0) { -+ rc = -ENODEV; -+ goto lirc_register_failed; -+ } -+ -+ ir_dev->raw->lirc.drv = drv; -+ ir_dev->raw->lirc.ir_dev = ir_dev; -+ ir_dev->raw->lirc.lircdata = PULSE_MASK; -+ -+ return 0; -+ -+lirc_register_failed: -+rbuf_init_failed: -+ kfree(rbuf); -+rbuf_alloc_failed: -+ kfree(drv); -+ -+ return rc; -+} -+ -+static int ir_lirc_unregister(struct input_dev *input_dev) -+{ -+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ struct lirc_codec *lirc = &ir_dev->raw->lirc; -+ -+ lirc_unregister_driver(lirc->drv->minor); -+ lirc_buffer_free(lirc->drv->rbuf); -+ kfree(lirc->drv); -+ -+ return 0; -+} -+ -+static struct ir_raw_handler lirc_handler = { -+ .protocols = IR_TYPE_LIRC, -+ .decode = ir_lirc_decode, -+ .raw_register = ir_lirc_register, -+ .raw_unregister = ir_lirc_unregister, -+}; -+ -+static int __init ir_lirc_codec_init(void) -+{ -+ ir_raw_handler_register(&lirc_handler); -+ -+ printk(KERN_INFO "IR LIRC bridge handler initialized\n"); -+ return 0; -+} -+ -+static void __exit ir_lirc_codec_exit(void) -+{ -+ ir_raw_handler_unregister(&lirc_handler); -+} -+ -+module_init(ir_lirc_codec_init); -+module_exit(ir_lirc_codec_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jarod Wilson "); -+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); -+MODULE_DESCRIPTION("LIRC IR handler bridge"); -diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c -index ba79233..52e0f37 100644 ---- a/drivers/media/IR/ir-nec-decoder.c -+++ b/drivers/media/IR/ir-nec-decoder.c -@@ -27,10 +27,6 @@ - #define NEC_TRAILER_PULSE (1 * NEC_UNIT) - #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ - --/* Used to register nec_decoder clients */ --static LIST_HEAD(decoder_list); --static DEFINE_SPINLOCK(decoder_lock); -- - enum nec_state { - STATE_INACTIVE, - STATE_HEADER_SPACE, -@@ -40,84 +36,6 @@ enum nec_state { - STATE_TRAILER_SPACE, - }; - --struct decoder_data { -- struct list_head list; -- struct ir_input_dev *ir_dev; -- int enabled:1; -- -- /* State machine control */ -- enum nec_state state; -- u32 nec_bits; -- unsigned count; --}; -- -- --/** -- * get_decoder_data() - gets decoder data -- * @input_dev: input device -- * -- * Returns the struct decoder_data that corresponds to a device -- */ --static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) --{ -- struct decoder_data *data = NULL; -- -- spin_lock(&decoder_lock); -- list_for_each_entry(data, &decoder_list, list) { -- if (data->ir_dev == ir_dev) -- break; -- } -- spin_unlock(&decoder_lock); -- return data; --} -- --static ssize_t store_enabled(struct device *d, -- struct device_attribute *mattr, -- const char *buf, -- size_t len) --{ -- unsigned long value; -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (strict_strtoul(buf, 10, &value) || value > 1) -- return -EINVAL; -- -- data->enabled = value; -- -- return len; --} -- --static ssize_t show_enabled(struct device *d, -- struct device_attribute *mattr, char *buf) --{ -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (data->enabled) -- return sprintf(buf, "1\n"); -- else -- return sprintf(buf, "0\n"); --} -- --static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); -- --static struct attribute *decoder_attributes[] = { -- &dev_attr_enabled.attr, -- NULL --}; -- --static struct attribute_group decoder_attribute_group = { -- .name = "nec_decoder", -- .attrs = decoder_attributes, --}; -- - /** - * ir_nec_decode() - Decode one NEC pulse or space - * @input_dev: the struct input_dev descriptor of the device -@@ -127,16 +45,12 @@ static struct attribute_group decoder_attribute_group = { - */ - static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) - { -- struct decoder_data *data; - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ struct nec_dec *data = &ir_dev->raw->nec; - u32 scancode; - u8 address, not_address, command, not_command; - -- data = get_decoder_data(ir_dev); -- if (!data) -- return -EINVAL; -- -- if (!data->enabled) -+ if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC)) - return 0; - - if (IS_RESET(ev)) { -@@ -191,9 +105,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) - if (ev.pulse) - break; - -- data->nec_bits <<= 1; -+ data->bits <<= 1; - if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) -- data->nec_bits |= 1; -+ data->bits |= 1; - else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) - break; - data->count++; -@@ -222,14 +136,14 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) - if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) - break; - -- address = bitrev8((data->nec_bits >> 24) & 0xff); -- not_address = bitrev8((data->nec_bits >> 16) & 0xff); -- command = bitrev8((data->nec_bits >> 8) & 0xff); -- not_command = bitrev8((data->nec_bits >> 0) & 0xff); -+ address = bitrev8((data->bits >> 24) & 0xff); -+ not_address = bitrev8((data->bits >> 16) & 0xff); -+ command = bitrev8((data->bits >> 8) & 0xff); -+ not_command = bitrev8((data->bits >> 0) & 0xff); - - if ((command ^ not_command) != 0xff) { - IR_dprintk(1, "NEC checksum error: received 0x%08x\n", -- data->nec_bits); -+ data->bits); - break; - } - -@@ -256,54 +170,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) - return -EINVAL; - } - --static int ir_nec_register(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- struct decoder_data *data; -- int rc; -- -- rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- if (rc < 0) -- return rc; -- -- data = kzalloc(sizeof(*data), GFP_KERNEL); -- if (!data) { -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- return -ENOMEM; -- } -- -- data->ir_dev = ir_dev; -- data->enabled = 1; -- -- spin_lock(&decoder_lock); -- list_add_tail(&data->list, &decoder_list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- --static int ir_nec_unregister(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- static struct decoder_data *data; -- -- data = get_decoder_data(ir_dev); -- if (!data) -- return 0; -- -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- -- spin_lock(&decoder_lock); -- list_del(&data->list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- - static struct ir_raw_handler nec_handler = { -+ .protocols = IR_TYPE_NEC, - .decode = ir_nec_decode, -- .raw_register = ir_nec_register, -- .raw_unregister = ir_nec_unregister, - }; - - static int __init ir_nec_decode_init(void) -diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c -index ea68a3f..6f192ef 100644 ---- a/drivers/media/IR/ir-raw-event.c -+++ b/drivers/media/IR/ir-raw-event.c -@@ -20,35 +20,13 @@ - /* Define the max number of pulse/space transitions to buffer */ - #define MAX_IR_EVENT_SIZE 512 - -+/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ -+static LIST_HEAD(ir_raw_client_list); -+ - /* Used to handle IR raw handler extensions */ --static LIST_HEAD(ir_raw_handler_list); - static DEFINE_SPINLOCK(ir_raw_handler_lock); -- --/** -- * RUN_DECODER() - runs an operation on all IR decoders -- * @ops: IR raw handler operation to be called -- * @arg: arguments to be passed to the callback -- * -- * Calls ir_raw_handler::ops for all registered IR handlers. It prevents -- * new decode addition/removal while running, by locking ir_raw_handler_lock -- * mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum -- * of the return codes. -- */ --#define RUN_DECODER(ops, ...) ({ \ -- struct ir_raw_handler *_ir_raw_handler; \ -- int _sumrc = 0, _rc; \ -- spin_lock(&ir_raw_handler_lock); \ -- list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \ -- if (_ir_raw_handler->ops) { \ -- _rc = _ir_raw_handler->ops(__VA_ARGS__); \ -- if (_rc < 0) \ -- break; \ -- _sumrc += _rc; \ -- } \ -- } \ -- spin_unlock(&ir_raw_handler_lock); \ -- _sumrc; \ --}) -+static LIST_HEAD(ir_raw_handler_list); -+static u64 available_protocols; - - #ifdef MODULE - /* Used to load the decoders */ -@@ -58,57 +36,17 @@ static struct work_struct wq_load; - static void ir_raw_event_work(struct work_struct *work) - { - struct ir_raw_event ev; -+ struct ir_raw_handler *handler; - struct ir_raw_event_ctrl *raw = - container_of(work, struct ir_raw_event_ctrl, rx_work); - -- while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) -- RUN_DECODER(decode, raw->input_dev, ev); --} -- --int ir_raw_event_register(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir = input_get_drvdata(input_dev); -- int rc; -- -- ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); -- if (!ir->raw) -- return -ENOMEM; -- -- ir->raw->input_dev = input_dev; -- INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); -- -- rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, -- GFP_KERNEL); -- if (rc < 0) { -- kfree(ir->raw); -- ir->raw = NULL; -- return rc; -- } -- -- rc = RUN_DECODER(raw_register, input_dev); -- if (rc < 0) { -- kfifo_free(&ir->raw->kfifo); -- kfree(ir->raw); -- ir->raw = NULL; -- return rc; -+ while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { -+ spin_lock(&ir_raw_handler_lock); -+ list_for_each_entry(handler, &ir_raw_handler_list, list) -+ handler->decode(raw->input_dev, ev); -+ spin_unlock(&ir_raw_handler_lock); -+ raw->prev_ev = ev; - } -- -- return rc; --} -- --void ir_raw_event_unregister(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir = input_get_drvdata(input_dev); -- -- if (!ir->raw) -- return; -- -- cancel_work_sync(&ir->raw->rx_work); -- RUN_DECODER(raw_unregister, input_dev); -- -- kfifo_free(&ir->raw->kfifo); -- kfree(ir->raw); -- ir->raw = NULL; - } - - /** -@@ -204,23 +142,103 @@ void ir_raw_event_handle(struct input_dev *input_dev) - } - EXPORT_SYMBOL_GPL(ir_raw_event_handle); - -+/* used internally by the sysfs interface */ -+u64 -+ir_raw_get_allowed_protocols() -+{ -+ u64 protocols; -+ spin_lock(&ir_raw_handler_lock); -+ protocols = available_protocols; -+ spin_unlock(&ir_raw_handler_lock); -+ return protocols; -+} -+ -+/* -+ * Used to (un)register raw event clients -+ */ -+int ir_raw_event_register(struct input_dev *input_dev) -+{ -+ struct ir_input_dev *ir = input_get_drvdata(input_dev); -+ int rc; -+ struct ir_raw_handler *handler; -+ -+ ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); -+ if (!ir->raw) -+ return -ENOMEM; -+ -+ ir->raw->input_dev = input_dev; -+ INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); -+ ir->raw->enabled_protocols = ~0; -+ rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, -+ GFP_KERNEL); -+ if (rc < 0) { -+ kfree(ir->raw); -+ ir->raw = NULL; -+ return rc; -+ } -+ -+ spin_lock(&ir_raw_handler_lock); -+ list_add_tail(&ir->raw->list, &ir_raw_client_list); -+ list_for_each_entry(handler, &ir_raw_handler_list, list) -+ if (handler->raw_register) -+ handler->raw_register(ir->raw->input_dev); -+ spin_unlock(&ir_raw_handler_lock); -+ -+ return 0; -+} -+ -+void ir_raw_event_unregister(struct input_dev *input_dev) -+{ -+ struct ir_input_dev *ir = input_get_drvdata(input_dev); -+ struct ir_raw_handler *handler; -+ -+ if (!ir->raw) -+ return; -+ -+ cancel_work_sync(&ir->raw->rx_work); -+ -+ spin_lock(&ir_raw_handler_lock); -+ list_del(&ir->raw->list); -+ list_for_each_entry(handler, &ir_raw_handler_list, list) -+ if (handler->raw_unregister) -+ handler->raw_unregister(ir->raw->input_dev); -+ spin_unlock(&ir_raw_handler_lock); -+ -+ kfifo_free(&ir->raw->kfifo); -+ kfree(ir->raw); -+ ir->raw = NULL; -+} -+ - /* - * Extension interface - used to register the IR decoders - */ - - int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) - { -+ struct ir_raw_event_ctrl *raw; -+ - spin_lock(&ir_raw_handler_lock); - list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); -+ if (ir_raw_handler->raw_register) -+ list_for_each_entry(raw, &ir_raw_client_list, list) -+ ir_raw_handler->raw_register(raw->input_dev); -+ available_protocols |= ir_raw_handler->protocols; - spin_unlock(&ir_raw_handler_lock); -+ - return 0; - } - EXPORT_SYMBOL(ir_raw_handler_register); - - void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) - { -+ struct ir_raw_event_ctrl *raw; -+ - spin_lock(&ir_raw_handler_lock); - list_del(&ir_raw_handler->list); -+ if (ir_raw_handler->raw_unregister) -+ list_for_each_entry(raw, &ir_raw_client_list, list) -+ ir_raw_handler->raw_unregister(raw->input_dev); -+ available_protocols &= ~ir_raw_handler->protocols; - spin_unlock(&ir_raw_handler_lock); - } - EXPORT_SYMBOL(ir_raw_handler_unregister); -@@ -235,6 +253,7 @@ static void init_decoders(struct work_struct *work) - load_rc6_decode(); - load_jvc_decode(); - load_sony_decode(); -+ load_lirc_codec(); - - /* If needed, we may later add some init code. In this case, - it is needed to change the CONFIG_MODULE test at ir-core.h -diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c -index 23cdb1b..df4770d 100644 ---- a/drivers/media/IR/ir-rc5-decoder.c -+++ b/drivers/media/IR/ir-rc5-decoder.c -@@ -30,10 +30,6 @@ - #define RC5_BIT_END (1 * RC5_UNIT) - #define RC5X_SPACE (4 * RC5_UNIT) - --/* Used to register rc5_decoder clients */ --static LIST_HEAD(decoder_list); --static DEFINE_SPINLOCK(decoder_lock); -- - enum rc5_state { - STATE_INACTIVE, - STATE_BIT_START, -@@ -42,87 +38,6 @@ enum rc5_state { - STATE_FINISHED, - }; - --struct decoder_data { -- struct list_head list; -- struct ir_input_dev *ir_dev; -- int enabled:1; -- -- /* State machine control */ -- enum rc5_state state; -- u32 rc5_bits; -- struct ir_raw_event prev_ev; -- unsigned count; -- unsigned wanted_bits; --}; -- -- --/** -- * get_decoder_data() - gets decoder data -- * @input_dev: input device -- * -- * Returns the struct decoder_data that corresponds to a device -- */ -- --static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) --{ -- struct decoder_data *data = NULL; -- -- spin_lock(&decoder_lock); -- list_for_each_entry(data, &decoder_list, list) { -- if (data->ir_dev == ir_dev) -- break; -- } -- spin_unlock(&decoder_lock); -- return data; --} -- --static ssize_t store_enabled(struct device *d, -- struct device_attribute *mattr, -- const char *buf, -- size_t len) --{ -- unsigned long value; -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (strict_strtoul(buf, 10, &value) || value > 1) -- return -EINVAL; -- -- data->enabled = value; -- -- return len; --} -- --static ssize_t show_enabled(struct device *d, -- struct device_attribute *mattr, char *buf) --{ -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (data->enabled) -- return sprintf(buf, "1\n"); -- else -- return sprintf(buf, "0\n"); --} -- --static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); -- --static struct attribute *decoder_attributes[] = { -- &dev_attr_enabled.attr, -- NULL --}; -- --static struct attribute_group decoder_attribute_group = { -- .name = "rc5_decoder", -- .attrs = decoder_attributes, --}; -- - /** - * ir_rc5_decode() - Decode one RC-5 pulse or space - * @input_dev: the struct input_dev descriptor of the device -@@ -132,17 +47,13 @@ static struct attribute_group decoder_attribute_group = { - */ - static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) - { -- struct decoder_data *data; - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ struct rc5_dec *data = &ir_dev->raw->rc5; - u8 toggle; - u32 scancode; - -- data = get_decoder_data(ir_dev); -- if (!data) -- return -EINVAL; -- -- if (!data->enabled) -- return 0; -+ if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5)) -+ return 0; - - if (IS_RESET(ev)) { - data->state = STATE_INACTIVE; -@@ -176,16 +87,15 @@ again: - if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) - break; - -- data->rc5_bits <<= 1; -+ data->bits <<= 1; - if (!ev.pulse) -- data->rc5_bits |= 1; -+ data->bits |= 1; - data->count++; -- data->prev_ev = ev; - data->state = STATE_BIT_END; - return 0; - - case STATE_BIT_END: -- if (!is_transition(&ev, &data->prev_ev)) -+ if (!is_transition(&ev, &ir_dev->raw->prev_ev)) - break; - - if (data->count == data->wanted_bits) -@@ -217,11 +127,11 @@ again: - if (data->wanted_bits == RC5X_NBITS) { - /* RC5X */ - u8 xdata, command, system; -- xdata = (data->rc5_bits & 0x0003F) >> 0; -- command = (data->rc5_bits & 0x00FC0) >> 6; -- system = (data->rc5_bits & 0x1F000) >> 12; -- toggle = (data->rc5_bits & 0x20000) ? 1 : 0; -- command += (data->rc5_bits & 0x01000) ? 0 : 0x40; -+ xdata = (data->bits & 0x0003F) >> 0; -+ command = (data->bits & 0x00FC0) >> 6; -+ system = (data->bits & 0x1F000) >> 12; -+ toggle = (data->bits & 0x20000) ? 1 : 0; -+ command += (data->bits & 0x01000) ? 0 : 0x40; - scancode = system << 16 | command << 8 | xdata; - - IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n", -@@ -230,10 +140,10 @@ again: - } else { - /* RC5 */ - u8 command, system; -- command = (data->rc5_bits & 0x0003F) >> 0; -- system = (data->rc5_bits & 0x007C0) >> 6; -- toggle = (data->rc5_bits & 0x00800) ? 1 : 0; -- command += (data->rc5_bits & 0x01000) ? 0 : 0x40; -+ command = (data->bits & 0x0003F) >> 0; -+ system = (data->bits & 0x007C0) >> 6; -+ toggle = (data->bits & 0x00800) ? 1 : 0; -+ command += (data->bits & 0x01000) ? 0 : 0x40; - scancode = system << 8 | command; - - IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", -@@ -252,54 +162,9 @@ out: - return -EINVAL; - } - --static int ir_rc5_register(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- struct decoder_data *data; -- int rc; -- -- rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- if (rc < 0) -- return rc; -- -- data = kzalloc(sizeof(*data), GFP_KERNEL); -- if (!data) { -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- return -ENOMEM; -- } -- -- data->ir_dev = ir_dev; -- data->enabled = 1; -- -- spin_lock(&decoder_lock); -- list_add_tail(&data->list, &decoder_list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- --static int ir_rc5_unregister(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- static struct decoder_data *data; -- -- data = get_decoder_data(ir_dev); -- if (!data) -- return 0; -- -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- -- spin_lock(&decoder_lock); -- list_del(&data->list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- - static struct ir_raw_handler rc5_handler = { -+ .protocols = IR_TYPE_RC5, - .decode = ir_rc5_decode, -- .raw_register = ir_rc5_register, -- .raw_unregister = ir_rc5_unregister, - }; - - static int __init ir_rc5_decode_init(void) -diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c -index 2bf479f..f1624b8 100644 ---- a/drivers/media/IR/ir-rc6-decoder.c -+++ b/drivers/media/IR/ir-rc6-decoder.c -@@ -36,10 +36,6 @@ - #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ - #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ - --/* Used to register rc6_decoder clients */ --static LIST_HEAD(decoder_list); --static DEFINE_SPINLOCK(decoder_lock); -- - enum rc6_mode { - RC6_MODE_0, - RC6_MODE_6A, -@@ -58,89 +54,8 @@ enum rc6_state { - STATE_FINISHED, - }; - --struct decoder_data { -- struct list_head list; -- struct ir_input_dev *ir_dev; -- int enabled:1; -- -- /* State machine control */ -- enum rc6_state state; -- u8 header; -- u32 body; -- struct ir_raw_event prev_ev; -- bool toggle; -- unsigned count; -- unsigned wanted_bits; --}; -- -- --/** -- * get_decoder_data() - gets decoder data -- * @input_dev: input device -- * -- * Returns the struct decoder_data that corresponds to a device -- */ --static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) --{ -- struct decoder_data *data = NULL; -- -- spin_lock(&decoder_lock); -- list_for_each_entry(data, &decoder_list, list) { -- if (data->ir_dev == ir_dev) -- break; -- } -- spin_unlock(&decoder_lock); -- return data; --} -- --static ssize_t store_enabled(struct device *d, -- struct device_attribute *mattr, -- const char *buf, -- size_t len) -+static enum rc6_mode rc6_mode(struct rc6_dec *data) - { -- unsigned long value; -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (strict_strtoul(buf, 10, &value) || value > 1) -- return -EINVAL; -- -- data->enabled = value; -- -- return len; --} -- --static ssize_t show_enabled(struct device *d, -- struct device_attribute *mattr, char *buf) --{ -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (data->enabled) -- return sprintf(buf, "1\n"); -- else -- return sprintf(buf, "0\n"); --} -- --static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); -- --static struct attribute *decoder_attributes[] = { -- &dev_attr_enabled.attr, -- NULL --}; -- --static struct attribute_group decoder_attribute_group = { -- .name = "rc6_decoder", -- .attrs = decoder_attributes, --}; -- --static enum rc6_mode rc6_mode(struct decoder_data *data) { - switch (data->header & RC6_MODE_MASK) { - case 0: - return RC6_MODE_0; -@@ -162,16 +77,12 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) { - */ - static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) - { -- struct decoder_data *data; - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ struct rc6_dec *data = &ir_dev->raw->rc6; - u32 scancode; - u8 toggle; - -- data = get_decoder_data(ir_dev); -- if (!data) -- return -EINVAL; -- -- if (!data->enabled) -+ if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) - return 0; - - if (IS_RESET(ev)) { -@@ -223,12 +134,11 @@ again: - if (ev.pulse) - data->header |= 1; - data->count++; -- data->prev_ev = ev; - data->state = STATE_HEADER_BIT_END; - return 0; - - case STATE_HEADER_BIT_END: -- if (!is_transition(&ev, &data->prev_ev)) -+ if (!is_transition(&ev, &ir_dev->raw->prev_ev)) - break; - - if (data->count == RC6_HEADER_NBITS) -@@ -244,12 +154,11 @@ again: - break; - - data->toggle = ev.pulse; -- data->prev_ev = ev; - data->state = STATE_TOGGLE_END; - return 0; - - case STATE_TOGGLE_END: -- if (!is_transition(&ev, &data->prev_ev) || -+ if (!is_transition(&ev, &ir_dev->raw->prev_ev) || - !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) - break; - -@@ -259,7 +168,6 @@ again: - } - - data->state = STATE_BODY_BIT_START; -- data->prev_ev = ev; - decrease_duration(&ev, RC6_TOGGLE_END); - data->count = 0; - -@@ -291,13 +199,11 @@ again: - if (ev.pulse) - data->body |= 1; - data->count++; -- data->prev_ev = ev; -- - data->state = STATE_BODY_BIT_END; - return 0; - - case STATE_BODY_BIT_END: -- if (!is_transition(&ev, &data->prev_ev)) -+ if (!is_transition(&ev, &ir_dev->raw->prev_ev)) - break; - - if (data->count == data->wanted_bits) -@@ -348,54 +254,9 @@ out: - return -EINVAL; - } - --static int ir_rc6_register(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- struct decoder_data *data; -- int rc; -- -- rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- if (rc < 0) -- return rc; -- -- data = kzalloc(sizeof(*data), GFP_KERNEL); -- if (!data) { -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- return -ENOMEM; -- } -- -- data->ir_dev = ir_dev; -- data->enabled = 1; -- -- spin_lock(&decoder_lock); -- list_add_tail(&data->list, &decoder_list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- --static int ir_rc6_unregister(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- static struct decoder_data *data; -- -- data = get_decoder_data(ir_dev); -- if (!data) -- return 0; -- -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- -- spin_lock(&decoder_lock); -- list_del(&data->list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- - static struct ir_raw_handler rc6_handler = { -+ .protocols = IR_TYPE_RC6, - .decode = ir_rc6_decode, -- .raw_register = ir_rc6_register, -- .raw_unregister = ir_rc6_unregister, - }; - - static int __init ir_rc6_decode_init(void) -diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c -index 9f440c5..b9074f0 100644 ---- a/drivers/media/IR/ir-sony-decoder.c -+++ b/drivers/media/IR/ir-sony-decoder.c -@@ -23,10 +23,6 @@ - #define SONY_BIT_SPACE (1 * SONY_UNIT) - #define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */ - --/* Used to register sony_decoder clients */ --static LIST_HEAD(decoder_list); --static DEFINE_SPINLOCK(decoder_lock); -- - enum sony_state { - STATE_INACTIVE, - STATE_HEADER_SPACE, -@@ -35,84 +31,6 @@ enum sony_state { - STATE_FINISHED, - }; - --struct decoder_data { -- struct list_head list; -- struct ir_input_dev *ir_dev; -- int enabled:1; -- -- /* State machine control */ -- enum sony_state state; -- u32 sony_bits; -- unsigned count; --}; -- -- --/** -- * get_decoder_data() - gets decoder data -- * @input_dev: input device -- * -- * Returns the struct decoder_data that corresponds to a device -- */ --static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) --{ -- struct decoder_data *data = NULL; -- -- spin_lock(&decoder_lock); -- list_for_each_entry(data, &decoder_list, list) { -- if (data->ir_dev == ir_dev) -- break; -- } -- spin_unlock(&decoder_lock); -- return data; --} -- --static ssize_t store_enabled(struct device *d, -- struct device_attribute *mattr, -- const char *buf, -- size_t len) --{ -- unsigned long value; -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (strict_strtoul(buf, 10, &value) || value > 1) -- return -EINVAL; -- -- data->enabled = value; -- -- return len; --} -- --static ssize_t show_enabled(struct device *d, -- struct device_attribute *mattr, char *buf) --{ -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- struct decoder_data *data = get_decoder_data(ir_dev); -- -- if (!data) -- return -EINVAL; -- -- if (data->enabled) -- return sprintf(buf, "1\n"); -- else -- return sprintf(buf, "0\n"); --} -- --static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); -- --static struct attribute *decoder_attributes[] = { -- &dev_attr_enabled.attr, -- NULL --}; -- --static struct attribute_group decoder_attribute_group = { -- .name = "sony_decoder", -- .attrs = decoder_attributes, --}; -- - /** - * ir_sony_decode() - Decode one Sony pulse or space - * @input_dev: the struct input_dev descriptor of the device -@@ -122,16 +40,12 @@ static struct attribute_group decoder_attribute_group = { - */ - static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) - { -- struct decoder_data *data; - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -+ struct sony_dec *data = &ir_dev->raw->sony; - u32 scancode; - u8 device, subdevice, function; - -- data = get_decoder_data(ir_dev); -- if (!data) -- return -EINVAL; -- -- if (!data->enabled) -+ if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) - return 0; - - if (IS_RESET(ev)) { -@@ -172,9 +86,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) - if (!ev.pulse) - break; - -- data->sony_bits <<= 1; -+ data->bits <<= 1; - if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2)) -- data->sony_bits |= 1; -+ data->bits |= 1; - else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2)) - break; - -@@ -208,19 +122,19 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) - - switch (data->count) { - case 12: -- device = bitrev8((data->sony_bits << 3) & 0xF8); -+ device = bitrev8((data->bits << 3) & 0xF8); - subdevice = 0; -- function = bitrev8((data->sony_bits >> 4) & 0xFE); -+ function = bitrev8((data->bits >> 4) & 0xFE); - break; - case 15: -- device = bitrev8((data->sony_bits >> 0) & 0xFF); -+ device = bitrev8((data->bits >> 0) & 0xFF); - subdevice = 0; -- function = bitrev8((data->sony_bits >> 7) & 0xFD); -+ function = bitrev8((data->bits >> 7) & 0xFD); - break; - case 20: -- device = bitrev8((data->sony_bits >> 5) & 0xF8); -- subdevice = bitrev8((data->sony_bits >> 0) & 0xFF); -- function = bitrev8((data->sony_bits >> 12) & 0xFE); -+ device = bitrev8((data->bits >> 5) & 0xF8); -+ subdevice = bitrev8((data->bits >> 0) & 0xFF); -+ function = bitrev8((data->bits >> 12) & 0xFE); - break; - default: - IR_dprintk(1, "Sony invalid bitcount %u\n", data->count); -@@ -241,54 +155,9 @@ out: - return -EINVAL; - } - --static int ir_sony_register(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- struct decoder_data *data; -- int rc; -- -- rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- if (rc < 0) -- return rc; -- -- data = kzalloc(sizeof(*data), GFP_KERNEL); -- if (!data) { -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- return -ENOMEM; -- } -- -- data->ir_dev = ir_dev; -- data->enabled = 1; -- -- spin_lock(&decoder_lock); -- list_add_tail(&data->list, &decoder_list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- --static int ir_sony_unregister(struct input_dev *input_dev) --{ -- struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- static struct decoder_data *data; -- -- data = get_decoder_data(ir_dev); -- if (!data) -- return 0; -- -- sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); -- -- spin_lock(&decoder_lock); -- list_del(&data->list); -- spin_unlock(&decoder_lock); -- -- return 0; --} -- - static struct ir_raw_handler sony_handler = { -+ .protocols = IR_TYPE_SONY, - .decode = ir_sony_decode, -- .raw_register = ir_sony_register, -- .raw_unregister = ir_sony_unregister, - }; - - static int __init ir_sony_decode_init(void) -diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c -index 2098dd1..a841e51 100644 ---- a/drivers/media/IR/ir-sysfs.c -+++ b/drivers/media/IR/ir-sysfs.c -@@ -34,122 +34,186 @@ static struct class ir_input_class = { - }; - - /** -- * show_protocol() - shows the current IR protocol -+ * show_protocols() - shows the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the output buffer - * -- * This routine is a callback routine for input read the IR protocol type. -- * it is trigged by reading /sys/class/rc/rc?/current_protocol. -- * It returns the protocol name, as understood by the driver. -+ * This routine is a callback routine for input read the IR protocol type(s). -+ * it is trigged by reading /sys/class/rc/rc?/protocols. -+ * It returns the protocol names of supported protocols. -+ * Enabled protocols are printed in brackets. - */ --static ssize_t show_protocol(struct device *d, -- struct device_attribute *mattr, char *buf) -+static ssize_t show_protocols(struct device *d, -+ struct device_attribute *mattr, char *buf) - { -- char *s; - struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- u64 ir_type = ir_dev->rc_tab.ir_type; -- -- IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type); -- -- /* FIXME: doesn't support multiple protocols at the same time */ -- if (ir_type == IR_TYPE_UNKNOWN) -- s = "Unknown"; -- else if (ir_type == IR_TYPE_RC5) -- s = "rc-5"; -- else if (ir_type == IR_TYPE_NEC) -- s = "nec"; -- else if (ir_type == IR_TYPE_RC6) -- s = "rc6"; -- else if (ir_type == IR_TYPE_JVC) -- s = "jvc"; -- else if (ir_type == IR_TYPE_SONY) -- s = "sony"; -- else -- s = "other"; -+ u64 allowed, enabled; -+ char *tmp = buf; -+ -+ if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { -+ enabled = ir_dev->rc_tab.ir_type; -+ allowed = ir_dev->props->allowed_protos; -+ } else { -+ enabled = ir_dev->raw->enabled_protocols; -+ allowed = ir_raw_get_allowed_protocols(); -+ } - -- return sprintf(buf, "%s\n", s); -+ IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", -+ (long long)allowed, -+ (long long)enabled); -+ -+ if (allowed & enabled & IR_TYPE_UNKNOWN) -+ tmp += sprintf(tmp, "[unknown] "); -+ else if (allowed & IR_TYPE_UNKNOWN) -+ tmp += sprintf(tmp, "unknown "); -+ -+ if (allowed & enabled & IR_TYPE_RC5) -+ tmp += sprintf(tmp, "[rc5] "); -+ else if (allowed & IR_TYPE_RC5) -+ tmp += sprintf(tmp, "rc5 "); -+ -+ if (allowed & enabled & IR_TYPE_NEC) -+ tmp += sprintf(tmp, "[nec] "); -+ else if (allowed & IR_TYPE_NEC) -+ tmp += sprintf(tmp, "nec "); -+ -+ if (allowed & enabled & IR_TYPE_RC6) -+ tmp += sprintf(tmp, "[rc6] "); -+ else if (allowed & IR_TYPE_RC6) -+ tmp += sprintf(tmp, "rc6 "); -+ -+ if (allowed & enabled & IR_TYPE_JVC) -+ tmp += sprintf(tmp, "[jvc] "); -+ else if (allowed & IR_TYPE_JVC) -+ tmp += sprintf(tmp, "jvc "); -+ -+ if (allowed & enabled & IR_TYPE_SONY) -+ tmp += sprintf(tmp, "[sony] "); -+ else if (allowed & IR_TYPE_SONY) -+ tmp += sprintf(tmp, "sony "); -+ -+ if (allowed & enabled & IR_TYPE_LIRC) -+ tmp += sprintf(tmp, "[lirc] "); -+ else if (allowed & IR_TYPE_LIRC) -+ tmp += sprintf(tmp, "lirc "); -+ -+ if (tmp != buf) -+ tmp--; -+ *tmp = '\n'; -+ return tmp + 1 - buf; - } - - /** -- * store_protocol() - shows the current IR protocol -+ * store_protocols() - changes the current IR protocol(s) - * @d: the device descriptor - * @mattr: the device attribute struct (unused) - * @buf: a pointer to the input buffer - * @len: length of the input buffer - * - * This routine is a callback routine for changing the IR protocol type. -- * it is trigged by reading /sys/class/rc/rc?/current_protocol. -- * It changes the IR the protocol name, if the IR type is recognized -- * by the driver. -- * If an unknown protocol name is used, returns -EINVAL. -+ * It is trigged by writing to /sys/class/rc/rc?/protocols. -+ * Writing "+proto" will add a protocol to the list of enabled protocols. -+ * Writing "-proto" will remove a protocol from the list of enabled protocols. -+ * Writing "proto" will enable only "proto". -+ * Returns -EINVAL if an invalid protocol combination or unknown protocol name -+ * is used, otherwise @len. - */ --static ssize_t store_protocol(struct device *d, -- struct device_attribute *mattr, -- const char *data, -- size_t len) -+static ssize_t store_protocols(struct device *d, -+ struct device_attribute *mattr, -+ const char *data, -+ size_t len) - { - struct ir_input_dev *ir_dev = dev_get_drvdata(d); -- u64 ir_type = 0; -- int rc = -EINVAL; -+ bool enable, disable; -+ const char *tmp; -+ u64 type; -+ u64 mask; -+ int rc; - unsigned long flags; -- char *buf; -- -- while ((buf = strsep((char **) &data, " \n")) != NULL) { -- if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) -- ir_type |= IR_TYPE_RC5; -- if (!strcasecmp(buf, "nec")) -- ir_type |= IR_TYPE_NEC; -- if (!strcasecmp(buf, "jvc")) -- ir_type |= IR_TYPE_JVC; -- if (!strcasecmp(buf, "sony")) -- ir_type |= IR_TYPE_SONY; -+ -+ tmp = skip_spaces(data); -+ -+ if (*tmp == '+') { -+ enable = true; -+ disable = false; -+ tmp++; -+ } else if (*tmp == '-') { -+ enable = false; -+ disable = true; -+ tmp++; -+ } else { -+ enable = false; -+ disable = false; - } - -- if (!ir_type) { -+ if (!strncasecmp(tmp, "unknown", 7)) { -+ tmp += 7; -+ mask = IR_TYPE_UNKNOWN; -+ } else if (!strncasecmp(tmp, "rc5", 3)) { -+ tmp += 3; -+ mask = IR_TYPE_RC5; -+ } else if (!strncasecmp(tmp, "nec", 3)) { -+ tmp += 3; -+ mask = IR_TYPE_NEC; -+ } else if (!strncasecmp(tmp, "rc6", 3)) { -+ tmp += 3; -+ mask = IR_TYPE_RC6; -+ } else if (!strncasecmp(tmp, "jvc", 3)) { -+ tmp += 3; -+ mask = IR_TYPE_JVC; -+ } else if (!strncasecmp(tmp, "sony", 4)) { -+ tmp += 4; -+ mask = IR_TYPE_SONY; -+ } else if (!strncasecmp(tmp, "lirc", 4)) { -+ tmp += 4; -+ mask = IR_TYPE_LIRC; -+ } else { - IR_dprintk(1, "Unknown protocol\n"); - return -EINVAL; - } - -- if (ir_dev->props && ir_dev->props->change_protocol) -- rc = ir_dev->props->change_protocol(ir_dev->props->priv, -- ir_type); -- -- if (rc < 0) { -- IR_dprintk(1, "Error setting protocol to %lld\n", -- (long long)ir_type); -+ tmp = skip_spaces(tmp); -+ if (*tmp != '\0') { -+ IR_dprintk(1, "Invalid trailing characters\n"); - return -EINVAL; - } - -- spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); -- ir_dev->rc_tab.ir_type = ir_type; -- spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); -+ if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) -+ type = ir_dev->rc_tab.ir_type; -+ else -+ type = ir_dev->raw->enabled_protocols; - -- IR_dprintk(1, "Current protocol(s) is(are) %lld\n", -- (long long)ir_type); -+ if (enable) -+ type |= mask; -+ else if (disable) -+ type &= ~mask; -+ else -+ type = mask; - -- return len; --} -+ if (ir_dev->props && ir_dev->props->change_protocol) { -+ rc = ir_dev->props->change_protocol(ir_dev->props->priv, -+ type); -+ if (rc < 0) { -+ IR_dprintk(1, "Error setting protocols to 0x%llx\n", -+ (long long)type); -+ return -EINVAL; -+ } -+ } - --static ssize_t show_supported_protocols(struct device *d, -- struct device_attribute *mattr, char *buf) --{ -- char *orgbuf = buf; -- struct ir_input_dev *ir_dev = dev_get_drvdata(d); -+ if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { -+ spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); -+ ir_dev->rc_tab.ir_type = type; -+ spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); -+ } else { -+ ir_dev->raw->enabled_protocols = type; -+ } - -- /* FIXME: doesn't support multiple protocols at the same time */ -- if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN) -- buf += sprintf(buf, "unknown "); -- if (ir_dev->props->allowed_protos & IR_TYPE_RC5) -- buf += sprintf(buf, "rc-5 "); -- if (ir_dev->props->allowed_protos & IR_TYPE_NEC) -- buf += sprintf(buf, "nec "); -- if (buf == orgbuf) -- buf += sprintf(buf, "other "); - -- buf += sprintf(buf - 1, "\n"); -+ IR_dprintk(1, "Current protocol(s): 0x%llx\n", -+ (long long)type); - -- return buf - orgbuf; -+ return len; - } - - #define ADD_HOTPLUG_VAR(fmt, val...) \ -@@ -159,7 +223,7 @@ static ssize_t show_supported_protocols(struct device *d, - return err; \ - } while (0) - --static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) -+static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env) - { - struct ir_input_dev *ir_dev = dev_get_drvdata(device); - -@@ -174,34 +238,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) - /* - * Static device attribute struct with the sysfs attributes for IR's - */ --static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR, -- show_protocol, store_protocol); -- --static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR, -- show_supported_protocols, NULL); -+static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR, -+ show_protocols, store_protocols); - --static struct attribute *ir_hw_dev_attrs[] = { -- &dev_attr_protocol.attr, -- &dev_attr_supported_protocols.attr, -+static struct attribute *rc_dev_attrs[] = { -+ &dev_attr_protocols.attr, - NULL, - }; - --static struct attribute_group ir_hw_dev_attr_grp = { -- .attrs = ir_hw_dev_attrs, -+static struct attribute_group rc_dev_attr_grp = { -+ .attrs = rc_dev_attrs, - }; - --static const struct attribute_group *ir_hw_dev_attr_groups[] = { -- &ir_hw_dev_attr_grp, -+static const struct attribute_group *rc_dev_attr_groups[] = { -+ &rc_dev_attr_grp, - NULL - }; - - static struct device_type rc_dev_type = { -- .groups = ir_hw_dev_attr_groups, -- .uevent = ir_dev_uevent, --}; -- --static struct device_type ir_raw_dev_type = { -- .uevent = ir_dev_uevent, -+ .groups = rc_dev_attr_groups, -+ .uevent = rc_dev_uevent, - }; - - /** -@@ -221,12 +277,7 @@ int ir_register_class(struct input_dev *input_dev) - if (unlikely(devno < 0)) - return devno; - -- if (ir_dev->props) { -- if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) -- ir_dev->dev.type = &rc_dev_type; -- } else -- ir_dev->dev.type = &ir_raw_dev_type; -- -+ ir_dev->dev.type = &rc_dev_type; - ir_dev->dev.class = &ir_input_class; - ir_dev->dev.parent = input_dev->dev.parent; - dev_set_name(&ir_dev->dev, "rc%d", devno); -diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile -index aea649f..86d3d1f 100644 ---- a/drivers/media/IR/keymaps/Makefile -+++ b/drivers/media/IR/keymaps/Makefile -@@ -37,6 +37,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-kaiomy.o \ - rc-kworld-315u.o \ - rc-kworld-plus-tv-analog.o \ -+ rc-lirc.o \ - rc-manli.o \ - rc-msi-tvanywhere.o \ - rc-msi-tvanywhere-plus.o \ -@@ -57,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-pv951.o \ - rc-rc5-hauppauge-new.o \ - rc-rc5-tv.o \ -+ rc-rc6-mce.o \ - rc-real-audio-220-32-keys.o \ - rc-tbs-nec.o \ - rc-terratec-cinergy-xs.o \ -diff --git a/drivers/media/IR/keymaps/rc-lirc.c b/drivers/media/IR/keymaps/rc-lirc.c -new file mode 100644 -index 0000000..43fcf90 ---- /dev/null -+++ b/drivers/media/IR/keymaps/rc-lirc.c -@@ -0,0 +1,41 @@ -+/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass -+ * all raw IR data to the lirc userspace decoder. -+ * -+ * Copyright (c) 2010 by Jarod Wilson -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+ -+static struct ir_scancode lirc[] = { -+ { }, -+}; -+ -+static struct rc_keymap lirc_map = { -+ .map = { -+ .scan = lirc, -+ .size = ARRAY_SIZE(lirc), -+ .ir_type = IR_TYPE_LIRC, -+ .name = RC_MAP_LIRC, -+ } -+}; -+ -+static int __init init_rc_map_lirc(void) -+{ -+ return ir_register_map(&lirc_map); -+} -+ -+static void __exit exit_rc_map_lirc(void) -+{ -+ ir_unregister_map(&lirc_map); -+} -+ -+module_init(init_rc_map_lirc) -+module_exit(exit_rc_map_lirc) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jarod Wilson "); -diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c -new file mode 100644 -index 0000000..c6726a8 ---- /dev/null -+++ b/drivers/media/IR/keymaps/rc-rc6-mce.c -@@ -0,0 +1,105 @@ -+/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use -+ * with the Media Center Edition eHome Infrared Transceiver. -+ * -+ * Copyright (c) 2010 by Jarod Wilson -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+ -+static struct ir_scancode rc6_mce[] = { -+ { 0x800f0415, KEY_REWIND }, -+ { 0x800f0414, KEY_FASTFORWARD }, -+ { 0x800f041b, KEY_PREVIOUS }, -+ { 0x800f041a, KEY_NEXT }, -+ -+ { 0x800f0416, KEY_PLAY }, -+ { 0x800f0418, KEY_PAUSE }, -+ { 0x800f0419, KEY_STOP }, -+ { 0x800f0417, KEY_RECORD }, -+ -+ { 0x800f041e, KEY_UP }, -+ { 0x800f041f, KEY_DOWN }, -+ { 0x800f0420, KEY_LEFT }, -+ { 0x800f0421, KEY_RIGHT }, -+ -+ { 0x800f040b, KEY_ENTER }, -+ { 0x800f0422, KEY_OK }, -+ { 0x800f0423, KEY_EXIT }, -+ { 0x800f040a, KEY_DELETE }, -+ -+ { 0x800f040e, KEY_MUTE }, -+ { 0x800f0410, KEY_VOLUMEUP }, -+ { 0x800f0411, KEY_VOLUMEDOWN }, -+ { 0x800f0412, KEY_CHANNELUP }, -+ { 0x800f0413, KEY_CHANNELDOWN }, -+ -+ { 0x800f0401, KEY_NUMERIC_1 }, -+ { 0x800f0402, KEY_NUMERIC_2 }, -+ { 0x800f0403, KEY_NUMERIC_3 }, -+ { 0x800f0404, KEY_NUMERIC_4 }, -+ { 0x800f0405, KEY_NUMERIC_5 }, -+ { 0x800f0406, KEY_NUMERIC_6 }, -+ { 0x800f0407, KEY_NUMERIC_7 }, -+ { 0x800f0408, KEY_NUMERIC_8 }, -+ { 0x800f0409, KEY_NUMERIC_9 }, -+ { 0x800f0400, KEY_NUMERIC_0 }, -+ -+ { 0x800f041d, KEY_NUMERIC_STAR }, -+ { 0x800f041c, KEY_NUMERIC_POUND }, -+ -+ { 0x800f0446, KEY_TV }, -+ { 0x800f0447, KEY_AUDIO }, /* My Music */ -+ { 0x800f0448, KEY_PVR }, /* RecordedTV */ -+ { 0x800f0449, KEY_CAMERA }, -+ { 0x800f044a, KEY_VIDEO }, -+ { 0x800f0424, KEY_DVD }, -+ { 0x800f0425, KEY_TUNER }, /* LiveTV */ -+ { 0x800f0450, KEY_RADIO }, -+ -+ { 0x800f044c, KEY_LANGUAGE }, -+ { 0x800f0427, KEY_ZOOM }, /* Aspect */ -+ -+ { 0x800f045b, KEY_RED }, -+ { 0x800f045c, KEY_GREEN }, -+ { 0x800f045d, KEY_YELLOW }, -+ { 0x800f045e, KEY_BLUE }, -+ -+ { 0x800f040f, KEY_INFO }, -+ { 0x800f0426, KEY_EPG }, /* Guide */ -+ { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */ -+ { 0x800f044d, KEY_TITLE }, -+ -+ { 0x800f040c, KEY_POWER }, -+ { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ -+ -+}; -+ -+static struct rc_keymap rc6_mce_map = { -+ .map = { -+ .scan = rc6_mce, -+ .size = ARRAY_SIZE(rc6_mce), -+ .ir_type = IR_TYPE_RC6, -+ .name = RC_MAP_RC6_MCE, -+ } -+}; -+ -+static int __init init_rc_map_rc6_mce(void) -+{ -+ return ir_register_map(&rc6_mce_map); -+} -+ -+static void __exit exit_rc_map_rc6_mce(void) -+{ -+ ir_unregister_map(&rc6_mce_map); -+} -+ -+module_init(init_rc_map_rc6_mce) -+module_exit(exit_rc_map_rc6_mce) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jarod Wilson "); -diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c -new file mode 100644 -index 0000000..899891b ---- /dev/null -+++ b/drivers/media/IR/lirc_dev.c -@@ -0,0 +1,764 @@ -+/* -+ * LIRC base driver -+ * -+ * by Artur Lipowski -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+static int debug; -+ -+#define IRCTL_DEV_NAME "BaseRemoteCtl" -+#define NOPLUG -1 -+#define LOGHEAD "lirc_dev (%s[%d]): " -+ -+static dev_t lirc_base_dev; -+ -+struct irctl { -+ struct lirc_driver d; -+ int attached; -+ int open; -+ -+ struct mutex irctl_lock; -+ struct lirc_buffer *buf; -+ unsigned int chunk_size; -+ -+ struct task_struct *task; -+ long jiffies_to_wait; -+ -+ struct cdev cdev; -+}; -+ -+static DEFINE_MUTEX(lirc_dev_lock); -+ -+static struct irctl *irctls[MAX_IRCTL_DEVICES]; -+ -+/* Only used for sysfs but defined to void otherwise */ -+static struct class *lirc_class; -+ -+/* helper function -+ * initializes the irctl structure -+ */ -+static void init_irctl(struct irctl *ir) -+{ -+ dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n", -+ ir->d.name, ir->d.minor); -+ mutex_init(&ir->irctl_lock); -+ ir->d.minor = NOPLUG; -+} -+ -+static void cleanup(struct irctl *ir) -+{ -+ dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); -+ -+ device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); -+ -+ if (ir->buf != ir->d.rbuf) { -+ lirc_buffer_free(ir->buf); -+ kfree(ir->buf); -+ } -+ ir->buf = NULL; -+} -+ -+/* helper function -+ * reads key codes from driver and puts them into buffer -+ * returns 0 on success -+ */ -+static int add_to_buf(struct irctl *ir) -+{ -+ if (ir->d.add_to_buf) { -+ int res = -ENODATA; -+ int got_data = 0; -+ -+ /* -+ * service the device as long as it is returning -+ * data and we have space -+ */ -+get_data: -+ res = ir->d.add_to_buf(ir->d.data, ir->buf); -+ if (res == 0) { -+ got_data++; -+ goto get_data; -+ } -+ -+ if (res == -ENODEV) -+ kthread_stop(ir->task); -+ -+ return got_data ? 0 : res; -+ } -+ -+ return 0; -+} -+ -+/* main function of the polling thread -+ */ -+static int lirc_thread(void *irctl) -+{ -+ struct irctl *ir = irctl; -+ -+ dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n", -+ ir->d.name, ir->d.minor); -+ -+ do { -+ if (ir->open) { -+ if (ir->jiffies_to_wait) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(ir->jiffies_to_wait); -+ } -+ if (kthread_should_stop()) -+ break; -+ if (!add_to_buf(ir)) -+ wake_up_interruptible(&ir->buf->wait_poll); -+ } else { -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule(); -+ } -+ } while (!kthread_should_stop()); -+ -+ dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n", -+ ir->d.name, ir->d.minor); -+ -+ return 0; -+} -+ -+ -+static struct file_operations fops = { -+ .owner = THIS_MODULE, -+ .read = lirc_dev_fop_read, -+ .write = lirc_dev_fop_write, -+ .poll = lirc_dev_fop_poll, -+ .unlocked_ioctl = lirc_dev_fop_ioctl, -+ .open = lirc_dev_fop_open, -+ .release = lirc_dev_fop_close, -+}; -+ -+static int lirc_cdev_add(struct irctl *ir) -+{ -+ int retval; -+ struct lirc_driver *d = &ir->d; -+ -+ if (d->fops) { -+ cdev_init(&ir->cdev, d->fops); -+ ir->cdev.owner = d->owner; -+ } else { -+ cdev_init(&ir->cdev, &fops); -+ ir->cdev.owner = THIS_MODULE; -+ } -+ kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor); -+ -+ retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); -+ if (retval) -+ kobject_put(&ir->cdev.kobj); -+ -+ return retval; -+} -+ -+int lirc_register_driver(struct lirc_driver *d) -+{ -+ struct irctl *ir; -+ int minor; -+ int bytes_in_key; -+ unsigned int chunk_size; -+ unsigned int buffer_size; -+ int err; -+ -+ if (!d) { -+ printk(KERN_ERR "lirc_dev: lirc_register_driver: " -+ "driver pointer must be not NULL!\n"); -+ err = -EBADRQC; -+ goto out; -+ } -+ -+ if (MAX_IRCTL_DEVICES <= d->minor) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "\"minor\" must be between 0 and %d (%d)!\n", -+ MAX_IRCTL_DEVICES-1, d->minor); -+ err = -EBADRQC; -+ goto out; -+ } -+ -+ if (1 > d->code_length || (BUFLEN * 8) < d->code_length) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "code length in bits for minor (%d) " -+ "must be less than %d!\n", -+ d->minor, BUFLEN * 8); -+ err = -EBADRQC; -+ goto out; -+ } -+ -+ dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n", -+ d->sample_rate); -+ if (d->sample_rate) { -+ if (2 > d->sample_rate || HZ < d->sample_rate) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "sample_rate must be between 2 and %d!\n", HZ); -+ err = -EBADRQC; -+ goto out; -+ } -+ if (!d->add_to_buf) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "add_to_buf cannot be NULL when " -+ "sample_rate is set\n"); -+ err = -EBADRQC; -+ goto out; -+ } -+ } else if (!(d->fops && d->fops->read) && !d->rbuf) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "fops->read and rbuf cannot all be NULL!\n"); -+ err = -EBADRQC; -+ goto out; -+ } else if (!d->rbuf) { -+ if (!(d->fops && d->fops->read && d->fops->poll && -+ d->fops->unlocked_ioctl)) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "neither read, poll nor unlocked_ioctl can be NULL!\n"); -+ err = -EBADRQC; -+ goto out; -+ } -+ } -+ -+ mutex_lock(&lirc_dev_lock); -+ -+ minor = d->minor; -+ -+ if (minor < 0) { -+ /* find first free slot for driver */ -+ for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) -+ if (!irctls[minor]) -+ break; -+ if (MAX_IRCTL_DEVICES == minor) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "no free slots for drivers!\n"); -+ err = -ENOMEM; -+ goto out_lock; -+ } -+ } else if (irctls[minor]) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "minor (%d) just registered!\n", minor); -+ err = -EBUSY; -+ goto out_lock; -+ } -+ -+ ir = kzalloc(sizeof(struct irctl), GFP_KERNEL); -+ if (!ir) { -+ err = -ENOMEM; -+ goto out_lock; -+ } -+ init_irctl(ir); -+ irctls[minor] = ir; -+ d->minor = minor; -+ -+ if (d->sample_rate) { -+ ir->jiffies_to_wait = HZ / d->sample_rate; -+ } else { -+ /* it means - wait for external event in task queue */ -+ ir->jiffies_to_wait = 0; -+ } -+ -+ /* some safety check 8-) */ -+ d->name[sizeof(d->name)-1] = '\0'; -+ -+ bytes_in_key = BITS_TO_LONGS(d->code_length) + -+ (d->code_length % 8 ? 1 : 0); -+ buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; -+ chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; -+ -+ if (d->rbuf) { -+ ir->buf = d->rbuf; -+ } else { -+ ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); -+ if (!ir->buf) { -+ err = -ENOMEM; -+ goto out_lock; -+ } -+ err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); -+ if (err) { -+ kfree(ir->buf); -+ goto out_lock; -+ } -+ } -+ ir->chunk_size = ir->buf->chunk_size; -+ -+ if (d->features == 0) -+ d->features = LIRC_CAN_REC_LIRCCODE; -+ -+ ir->d = *d; -+ ir->d.minor = minor; -+ -+ device_create(lirc_class, ir->d.dev, -+ MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL, -+ "lirc%u", ir->d.minor); -+ -+ if (d->sample_rate) { -+ /* try to fire up polling thread */ -+ ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev"); -+ if (IS_ERR(ir->task)) { -+ dev_err(d->dev, "lirc_dev: lirc_register_driver: " -+ "cannot run poll thread for minor = %d\n", -+ d->minor); -+ err = -ECHILD; -+ goto out_sysfs; -+ } -+ } -+ -+ err = lirc_cdev_add(ir); -+ if (err) -+ goto out_sysfs; -+ -+ ir->attached = 1; -+ mutex_unlock(&lirc_dev_lock); -+ -+ dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", -+ ir->d.name, ir->d.minor); -+ return minor; -+ -+out_sysfs: -+ device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); -+out_lock: -+ mutex_unlock(&lirc_dev_lock); -+out: -+ return err; -+} -+EXPORT_SYMBOL(lirc_register_driver); -+ -+int lirc_unregister_driver(int minor) -+{ -+ struct irctl *ir; -+ -+ if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { -+ printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " -+ "\"minor (%d)\" must be between 0 and %d!\n", -+ minor, MAX_IRCTL_DEVICES-1); -+ return -EBADRQC; -+ } -+ -+ ir = irctls[minor]; -+ -+ mutex_lock(&lirc_dev_lock); -+ -+ if (ir->d.minor != minor) { -+ printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " -+ "minor (%d) device not registered!", minor); -+ mutex_unlock(&lirc_dev_lock); -+ return -ENOENT; -+ } -+ -+ /* end up polling thread */ -+ if (ir->task) -+ kthread_stop(ir->task); -+ -+ dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", -+ ir->d.name, ir->d.minor); -+ -+ ir->attached = 0; -+ if (ir->open) { -+ dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", -+ ir->d.name, ir->d.minor); -+ wake_up_interruptible(&ir->buf->wait_poll); -+ mutex_lock(&ir->irctl_lock); -+ ir->d.set_use_dec(ir->d.data); -+ module_put(ir->d.owner); -+ mutex_unlock(&ir->irctl_lock); -+ cdev_del(&ir->cdev); -+ } else { -+ cleanup(ir); -+ cdev_del(&ir->cdev); -+ kfree(ir); -+ irctls[minor] = NULL; -+ } -+ -+ mutex_unlock(&lirc_dev_lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL(lirc_unregister_driver); -+ -+int lirc_dev_fop_open(struct inode *inode, struct file *file) -+{ -+ struct irctl *ir; -+ int retval = 0; -+ -+ if (iminor(inode) >= MAX_IRCTL_DEVICES) { -+ printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n", -+ iminor(inode)); -+ return -ENODEV; -+ } -+ -+ if (mutex_lock_interruptible(&lirc_dev_lock)) -+ return -ERESTARTSYS; -+ -+ ir = irctls[iminor(inode)]; -+ if (!ir) { -+ retval = -ENODEV; -+ goto error; -+ } -+ file->private_data = ir; -+ -+ dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); -+ -+ if (ir->d.minor == NOPLUG) { -+ retval = -ENODEV; -+ goto error; -+ } -+ -+ if (ir->open) { -+ retval = -EBUSY; -+ goto error; -+ } -+ -+ if (try_module_get(ir->d.owner)) { -+ ++ir->open; -+ retval = ir->d.set_use_inc(ir->d.data); -+ -+ if (retval) { -+ module_put(ir->d.owner); -+ --ir->open; -+ } else { -+ lirc_buffer_clear(ir->buf); -+ } -+ if (ir->task) -+ wake_up_process(ir->task); -+ } -+ -+error: -+ if (ir) -+ dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n", -+ ir->d.name, ir->d.minor, retval); -+ -+ mutex_unlock(&lirc_dev_lock); -+ -+ return retval; -+} -+EXPORT_SYMBOL(lirc_dev_fop_open); -+ -+int lirc_dev_fop_close(struct inode *inode, struct file *file) -+{ -+ struct irctl *ir = irctls[iminor(inode)]; -+ -+ dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); -+ -+ WARN_ON(mutex_lock_killable(&lirc_dev_lock)); -+ -+ --ir->open; -+ if (ir->attached) { -+ ir->d.set_use_dec(ir->d.data); -+ module_put(ir->d.owner); -+ } else { -+ cleanup(ir); -+ irctls[ir->d.minor] = NULL; -+ kfree(ir); -+ } -+ -+ mutex_unlock(&lirc_dev_lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL(lirc_dev_fop_close); -+ -+unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) -+{ -+ struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; -+ unsigned int ret; -+ -+ dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); -+ -+ if (!ir->attached) { -+ mutex_unlock(&ir->irctl_lock); -+ return POLLERR; -+ } -+ -+ poll_wait(file, &ir->buf->wait_poll, wait); -+ -+ if (ir->buf) -+ if (lirc_buffer_empty(ir->buf)) -+ ret = 0; -+ else -+ ret = POLLIN | POLLRDNORM; -+ else -+ ret = POLLERR; -+ -+ dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", -+ ir->d.name, ir->d.minor, ret); -+ -+ return ret; -+} -+EXPORT_SYMBOL(lirc_dev_fop_poll); -+ -+long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ unsigned long mode; -+ int result = 0; -+ struct irctl *ir = file->private_data; -+ -+ dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", -+ ir->d.name, ir->d.minor, cmd); -+ -+ if (ir->d.minor == NOPLUG || !ir->attached) { -+ dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n", -+ ir->d.name, ir->d.minor); -+ return -ENODEV; -+ } -+ -+ mutex_lock(&ir->irctl_lock); -+ -+ switch (cmd) { -+ case LIRC_GET_FEATURES: -+ result = put_user(ir->d.features, (unsigned long *)arg); -+ break; -+ case LIRC_GET_REC_MODE: -+ if (!(ir->d.features & LIRC_CAN_REC_MASK)) { -+ result = -ENOSYS; -+ break; -+ } -+ -+ result = put_user(LIRC_REC2MODE -+ (ir->d.features & LIRC_CAN_REC_MASK), -+ (unsigned long *)arg); -+ break; -+ case LIRC_SET_REC_MODE: -+ if (!(ir->d.features & LIRC_CAN_REC_MASK)) { -+ result = -ENOSYS; -+ break; -+ } -+ -+ result = get_user(mode, (unsigned long *)arg); -+ if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) -+ result = -EINVAL; -+ /* -+ * FIXME: We should actually set the mode somehow but -+ * for now, lirc_serial doesn't support mode changing either -+ */ -+ break; -+ case LIRC_GET_LENGTH: -+ result = put_user(ir->d.code_length, (unsigned long *)arg); -+ break; -+ case LIRC_GET_MIN_TIMEOUT: -+ if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || -+ ir->d.min_timeout == 0) { -+ result = -ENOSYS; -+ break; -+ } -+ -+ result = put_user(ir->d.min_timeout, (unsigned long *)arg); -+ break; -+ case LIRC_GET_MAX_TIMEOUT: -+ if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || -+ ir->d.max_timeout == 0) { -+ result = -ENOSYS; -+ break; -+ } -+ -+ result = put_user(ir->d.max_timeout, (unsigned long *)arg); -+ break; -+ default: -+ result = -EINVAL; -+ } -+ -+ dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n", -+ ir->d.name, ir->d.minor, result); -+ -+ mutex_unlock(&ir->irctl_lock); -+ -+ return result; -+} -+EXPORT_SYMBOL(lirc_dev_fop_ioctl); -+ -+ssize_t lirc_dev_fop_read(struct file *file, -+ char *buffer, -+ size_t length, -+ loff_t *ppos) -+{ -+ struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; -+ unsigned char buf[ir->chunk_size]; -+ int ret = 0, written = 0; -+ DECLARE_WAITQUEUE(wait, current); -+ -+ dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); -+ -+ if (mutex_lock_interruptible(&ir->irctl_lock)) -+ return -ERESTARTSYS; -+ if (!ir->attached) { -+ mutex_unlock(&ir->irctl_lock); -+ return -ENODEV; -+ } -+ -+ if (length % ir->chunk_size) { -+ dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n", -+ ir->d.name, ir->d.minor); -+ mutex_unlock(&ir->irctl_lock); -+ return -EINVAL; -+ } -+ -+ /* -+ * we add ourselves to the task queue before buffer check -+ * to avoid losing scan code (in case when queue is awaken somewhere -+ * between while condition checking and scheduling) -+ */ -+ add_wait_queue(&ir->buf->wait_poll, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ /* -+ * while we didn't provide 'length' bytes, device is opened in blocking -+ * mode and 'copy_to_user' is happy, wait for data. -+ */ -+ while (written < length && ret == 0) { -+ if (lirc_buffer_empty(ir->buf)) { -+ /* According to the read(2) man page, 'written' can be -+ * returned as less than 'length', instead of blocking -+ * again, returning -EWOULDBLOCK, or returning -+ * -ERESTARTSYS */ -+ if (written) -+ break; -+ if (file->f_flags & O_NONBLOCK) { -+ ret = -EWOULDBLOCK; -+ break; -+ } -+ if (signal_pending(current)) { -+ ret = -ERESTARTSYS; -+ break; -+ } -+ -+ mutex_unlock(&ir->irctl_lock); -+ schedule(); -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ if (mutex_lock_interruptible(&ir->irctl_lock)) { -+ ret = -ERESTARTSYS; -+ remove_wait_queue(&ir->buf->wait_poll, &wait); -+ set_current_state(TASK_RUNNING); -+ goto out_unlocked; -+ } -+ -+ if (!ir->attached) { -+ ret = -ENODEV; -+ break; -+ } -+ } else { -+ lirc_buffer_read(ir->buf, buf); -+ ret = copy_to_user((void *)buffer+written, buf, -+ ir->buf->chunk_size); -+ written += ir->buf->chunk_size; -+ } -+ } -+ -+ remove_wait_queue(&ir->buf->wait_poll, &wait); -+ set_current_state(TASK_RUNNING); -+ mutex_unlock(&ir->irctl_lock); -+ -+out_unlocked: -+ dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", -+ ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); -+ -+ return ret ? ret : written; -+} -+EXPORT_SYMBOL(lirc_dev_fop_read); -+ -+void *lirc_get_pdata(struct file *file) -+{ -+ void *data = NULL; -+ -+ if (file && file->f_dentry && file->f_dentry->d_inode && -+ file->f_dentry->d_inode->i_rdev) { -+ struct irctl *ir; -+ ir = irctls[iminor(file->f_dentry->d_inode)]; -+ data = ir->d.data; -+ } -+ -+ return data; -+} -+EXPORT_SYMBOL(lirc_get_pdata); -+ -+ -+ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, -+ size_t length, loff_t *ppos) -+{ -+ struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; -+ -+ dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor); -+ -+ if (!ir->attached) -+ return -ENODEV; -+ -+ return -EINVAL; -+} -+EXPORT_SYMBOL(lirc_dev_fop_write); -+ -+ -+static int __init lirc_dev_init(void) -+{ -+ int retval; -+ -+ lirc_class = class_create(THIS_MODULE, "lirc"); -+ if (IS_ERR(lirc_class)) { -+ retval = PTR_ERR(lirc_class); -+ printk(KERN_ERR "lirc_dev: class_create failed\n"); -+ goto error; -+ } -+ -+ retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, -+ IRCTL_DEV_NAME); -+ if (retval) { -+ class_destroy(lirc_class); -+ printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n"); -+ goto error; -+ } -+ -+ -+ printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, " -+ "major %d \n", MAJOR(lirc_base_dev)); -+ -+error: -+ return retval; -+} -+ -+ -+ -+static void __exit lirc_dev_exit(void) -+{ -+ class_destroy(lirc_class); -+ unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); -+ printk(KERN_INFO "lirc_dev: module unloaded\n"); -+} -+ -+module_init(lirc_dev_init); -+module_exit(lirc_dev_exit); -+ -+MODULE_DESCRIPTION("LIRC base driver module"); -+MODULE_AUTHOR("Artur Lipowski"); -+MODULE_LICENSE("GPL"); -+ -+module_param(debug, bool, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Enable debugging messages"); -diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c -new file mode 100644 -index 0000000..78bf7f7 ---- /dev/null -+++ b/drivers/media/IR/mceusb.c -@@ -0,0 +1,1143 @@ -+/* -+ * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers -+ * -+ * Copyright (c) 2010 by Jarod Wilson -+ * -+ * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan -+ * Conti, Martin Blatter and Daniel Melander, the latter of which was -+ * in turn also based on the lirc_atiusb driver by Paul Miller. The -+ * two mce drivers were merged into one by Jarod Wilson, with transmit -+ * support for the 1st-gen device added primarily by Patrick Calhoun, -+ * with a bit of tweaks by Jarod. Debugging improvements and proper -+ * support for what appears to be 3rd-gen hardware added by Jarod. -+ * Initial port from lirc driver to ir-core drivery by Jarod, based -+ * partially on a port to an earlier proposed IR infrastructure by -+ * Jon Smirl, which included enhancements and simplifications to the -+ * incoming IR buffer parsing routines. -+ * -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_VERSION "1.91" -+#define DRIVER_AUTHOR "Jarod Wilson " -+#define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ -+ "device driver" -+#define DRIVER_NAME "mceusb" -+ -+#define USB_BUFLEN 32 /* USB reception buffer length */ -+#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ -+#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ -+ -+/* MCE constants */ -+#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ -+#define MCE_TIME_UNIT 50 /* Approx 50us resolution */ -+#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ -+#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ -+#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ -+#define MCE_CONTROL_HEADER 0x9F /* MCE status header */ -+#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */ -+#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ -+#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */ -+#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */ -+#define MCE_PULSE_MASK 0x7F /* Pulse mask */ -+#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */ -+#define MCE_PACKET_LENGTH_MASK 0x1F /* Packet length mask */ -+ -+ -+/* module parameters */ -+#ifdef CONFIG_USB_DEBUG -+static int debug = 1; -+#else -+static int debug; -+#endif -+ -+/* general constants */ -+#define SEND_FLAG_IN_PROGRESS 1 -+#define SEND_FLAG_COMPLETE 2 -+#define RECV_FLAG_IN_PROGRESS 3 -+#define RECV_FLAG_COMPLETE 4 -+ -+#define MCEUSB_RX 1 -+#define MCEUSB_TX 2 -+ -+#define VENDOR_PHILIPS 0x0471 -+#define VENDOR_SMK 0x0609 -+#define VENDOR_TATUNG 0x1460 -+#define VENDOR_GATEWAY 0x107b -+#define VENDOR_SHUTTLE 0x1308 -+#define VENDOR_SHUTTLE2 0x051c -+#define VENDOR_MITSUMI 0x03ee -+#define VENDOR_TOPSEED 0x1784 -+#define VENDOR_RICAVISION 0x179d -+#define VENDOR_ITRON 0x195d -+#define VENDOR_FIC 0x1509 -+#define VENDOR_LG 0x043e -+#define VENDOR_MICROSOFT 0x045e -+#define VENDOR_FORMOSA 0x147a -+#define VENDOR_FINTEK 0x1934 -+#define VENDOR_PINNACLE 0x2304 -+#define VENDOR_ECS 0x1019 -+#define VENDOR_WISTRON 0x0fb8 -+#define VENDOR_COMPRO 0x185b -+#define VENDOR_NORTHSTAR 0x04eb -+#define VENDOR_REALTEK 0x0bda -+#define VENDOR_TIVO 0x105a -+ -+static struct usb_device_id mceusb_dev_table[] = { -+ /* Original Microsoft MCE IR Transceiver (often HP-branded) */ -+ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, -+ /* Philips Infrared Transceiver - Sahara branded */ -+ { USB_DEVICE(VENDOR_PHILIPS, 0x0608) }, -+ /* Philips Infrared Transceiver - HP branded */ -+ { USB_DEVICE(VENDOR_PHILIPS, 0x060c) }, -+ /* Philips SRM5100 */ -+ { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, -+ /* Philips Infrared Transceiver - Omaura */ -+ { USB_DEVICE(VENDOR_PHILIPS, 0x060f) }, -+ /* Philips Infrared Transceiver - Spinel plus */ -+ { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, -+ /* Philips eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, -+ /* Realtek MCE IR Receiver */ -+ { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, -+ /* SMK/Toshiba G83C0004D410 */ -+ { USB_DEVICE(VENDOR_SMK, 0x031d) }, -+ /* SMK eHome Infrared Transceiver (Sony VAIO) */ -+ { USB_DEVICE(VENDOR_SMK, 0x0322) }, -+ /* bundled with Hauppauge PVR-150 */ -+ { USB_DEVICE(VENDOR_SMK, 0x0334) }, -+ /* SMK eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_SMK, 0x0338) }, -+ /* Tatung eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, -+ /* Shuttle eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, -+ /* Shuttle eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, -+ /* Gateway eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, -+ /* Mitsumi */ -+ { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, -+ /* Topseed eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, -+ /* Topseed HP eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, -+ /* Topseed eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, -+ /* Topseed eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, -+ /* Topseed eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_TOPSEED, 0x000a) }, -+ /* Topseed eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0011) }, -+ /* Ricavision internal Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, -+ /* Itron ione Libra Q-11 */ -+ { USB_DEVICE(VENDOR_ITRON, 0x7002) }, -+ /* FIC eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_FIC, 0x9242) }, -+ /* LG eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_LG, 0x9803) }, -+ /* Microsoft MCE Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, -+ /* Formosa eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, -+ /* Formosa21 / eHome Infrared Receiver */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, -+ /* Formosa aim / Trust MCE Infrared Receiver */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, -+ /* Formosa Industrial Computing / Beanbag Emulation Device */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, -+ /* Formosa21 / eHome Infrared Receiver */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) }, -+ /* Formosa Industrial Computing AIM IR605/A */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, -+ /* Formosa Industrial Computing */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, -+ /* Fintek eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, -+ /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ -+ { USB_DEVICE(VENDOR_FINTEK, 0x0702) }, -+ /* Pinnacle Remote Kit */ -+ { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, -+ /* Elitegroup Computer Systems IR */ -+ { USB_DEVICE(VENDOR_ECS, 0x0f38) }, -+ /* Wistron Corp. eHome Infrared Receiver */ -+ { USB_DEVICE(VENDOR_WISTRON, 0x0002) }, -+ /* Compro K100 */ -+ { USB_DEVICE(VENDOR_COMPRO, 0x3020) }, -+ /* Compro K100 v2 */ -+ { USB_DEVICE(VENDOR_COMPRO, 0x3082) }, -+ /* Northstar Systems, Inc. eHome Infrared Transceiver */ -+ { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, -+ /* TiVo PC IR Receiver */ -+ { USB_DEVICE(VENDOR_TIVO, 0x2000) }, -+ /* Terminating entry */ -+ { } -+}; -+ -+static struct usb_device_id gen3_list[] = { -+ { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, -+ {} -+}; -+ -+static struct usb_device_id microsoft_gen1_list[] = { -+ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, -+ {} -+}; -+ -+static struct usb_device_id std_tx_mask_list[] = { -+ { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, -+ { USB_DEVICE(VENDOR_PHILIPS, 0x060c) }, -+ { USB_DEVICE(VENDOR_SMK, 0x031d) }, -+ { USB_DEVICE(VENDOR_SMK, 0x0322) }, -+ { USB_DEVICE(VENDOR_SMK, 0x0334) }, -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, -+ { USB_DEVICE(VENDOR_TOPSEED, 0x000a) }, -+ { USB_DEVICE(VENDOR_TOPSEED, 0x0011) }, -+ { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, -+ {} -+}; -+ -+/* data structure for each usb transceiver */ -+struct mceusb_dev { -+ /* ir-core bits */ -+ struct ir_input_dev *irdev; -+ struct ir_dev_props *props; -+ struct ir_raw_event rawir; -+ -+ /* core device bits */ -+ struct device *dev; -+ struct input_dev *idev; -+ -+ /* usb */ -+ struct usb_device *usbdev; -+ struct urb *urb_in; -+ struct usb_endpoint_descriptor *usb_ep_in; -+ struct usb_endpoint_descriptor *usb_ep_out; -+ -+ /* buffers and dma */ -+ unsigned char *buf_in; -+ unsigned int len_in; -+ u8 cmd; /* MCE command type */ -+ u8 rem; /* Remaining IR data bytes in packet */ -+ dma_addr_t dma_in; -+ dma_addr_t dma_out; -+ -+ struct { -+ u32 connected:1; -+ u32 tx_mask_inverted:1; -+ u32 microsoft_gen1:1; -+ u32 reserved:29; -+ } flags; -+ -+ /* transmit support */ -+ int send_flags; -+ u32 carrier; -+ unsigned char tx_mask; -+ -+ char name[128]; -+ char phys[64]; -+}; -+ -+/* -+ * MCE Device Command Strings -+ * Device command responses vary from device to device... -+ * - DEVICE_RESET resets the hardware to its default state -+ * - GET_REVISION fetches the hardware/software revision, common -+ * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42 -+ * - GET_CARRIER_FREQ gets the carrier mode and frequency of the -+ * device, with replies in the form of 9f 06 MM FF, where MM is 0-3, -+ * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is -+ * ((clk / frequency) - 1) -+ * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us, -+ * response in the form of 9f 0c msb lsb -+ * - GET_TX_BITMASK fetches the transmitter bitmask, replies in -+ * the form of 9f 08 bm, where bm is the bitmask -+ * - GET_RX_SENSOR fetches the RX sensor setting -- long-range -+ * general use one or short-range learning one, in the form of -+ * 9f 14 ss, where ss is either 01 for long-range or 02 for short -+ * - SET_CARRIER_FREQ sets a new carrier mode and frequency -+ * - SET_TX_BITMASK sets the transmitter bitmask -+ * - SET_RX_TIMEOUT sets the receiver timeout -+ * - SET_RX_SENSOR sets which receiver sensor to use -+ */ -+static char DEVICE_RESET[] = {0x00, 0xff, 0xaa}; -+static char GET_REVISION[] = {0xff, 0x0b}; -+static char GET_UNKNOWN[] = {0xff, 0x18}; -+static char GET_UNKNOWN2[] = {0x9f, 0x05}; -+static char GET_CARRIER_FREQ[] = {0x9f, 0x07}; -+static char GET_RX_TIMEOUT[] = {0x9f, 0x0d}; -+static char GET_TX_BITMASK[] = {0x9f, 0x13}; -+static char GET_RX_SENSOR[] = {0x9f, 0x15}; -+/* sub in desired values in lower byte or bytes for full command */ -+/* FIXME: make use of these for transmit. -+static char SET_CARRIER_FREQ[] = {0x9f, 0x06, 0x00, 0x00}; -+static char SET_TX_BITMASK[] = {0x9f, 0x08, 0x00}; -+static char SET_RX_TIMEOUT[] = {0x9f, 0x0c, 0x00, 0x00}; -+static char SET_RX_SENSOR[] = {0x9f, 0x14, 0x00}; -+*/ -+ -+static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, -+ int len, bool out) -+{ -+ char codes[USB_BUFLEN * 3 + 1]; -+ char inout[9]; -+ int i; -+ u8 cmd, subcmd, data1, data2; -+ struct device *dev = ir->dev; -+ int idx = 0; -+ -+ /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ -+ if (ir->flags.microsoft_gen1 && !out) -+ idx = 2; -+ -+ if (len <= idx) -+ return; -+ -+ for (i = 0; i < len && i < USB_BUFLEN; i++) -+ snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF); -+ -+ dev_info(dev, "%sx data: %s (length=%d)\n", -+ (out ? "t" : "r"), codes, len); -+ -+ if (out) -+ strcpy(inout, "Request\0"); -+ else -+ strcpy(inout, "Got\0"); -+ -+ cmd = buf[idx] & 0xff; -+ subcmd = buf[idx + 1] & 0xff; -+ data1 = buf[idx + 2] & 0xff; -+ data2 = buf[idx + 3] & 0xff; -+ -+ switch (cmd) { -+ case 0x00: -+ if (subcmd == 0xff && data1 == 0xaa) -+ dev_info(dev, "Device reset requested\n"); -+ else -+ dev_info(dev, "Unknown command 0x%02x 0x%02x\n", -+ cmd, subcmd); -+ break; -+ case 0xff: -+ switch (subcmd) { -+ case 0x0b: -+ if (len == 2) -+ dev_info(dev, "Get hw/sw rev?\n"); -+ else -+ dev_info(dev, "hw/sw rev 0x%02x 0x%02x " -+ "0x%02x 0x%02x\n", data1, data2, -+ buf[idx + 4], buf[idx + 5]); -+ break; -+ case 0xaa: -+ dev_info(dev, "Device reset requested\n"); -+ break; -+ case 0xfe: -+ dev_info(dev, "Previous command not supported\n"); -+ break; -+ case 0x18: -+ case 0x1b: -+ default: -+ dev_info(dev, "Unknown command 0x%02x 0x%02x\n", -+ cmd, subcmd); -+ break; -+ } -+ break; -+ case 0x9f: -+ switch (subcmd) { -+ case 0x03: -+ dev_info(dev, "Ping\n"); -+ break; -+ case 0x04: -+ dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n", -+ data1, data2); -+ break; -+ case 0x06: -+ dev_info(dev, "%s carrier mode and freq of " -+ "0x%02x 0x%02x\n", inout, data1, data2); -+ break; -+ case 0x07: -+ dev_info(dev, "Get carrier mode and freq\n"); -+ break; -+ case 0x08: -+ dev_info(dev, "%s transmit blaster mask of 0x%02x\n", -+ inout, data1); -+ break; -+ case 0x0c: -+ /* value is in units of 50us, so x*50/100 or x/2 ms */ -+ dev_info(dev, "%s receive timeout of %d ms\n", -+ inout, ((data1 << 8) | data2) / 2); -+ break; -+ case 0x0d: -+ dev_info(dev, "Get receive timeout\n"); -+ break; -+ case 0x13: -+ dev_info(dev, "Get transmit blaster mask\n"); -+ break; -+ case 0x14: -+ dev_info(dev, "%s %s-range receive sensor in use\n", -+ inout, data1 == 0x02 ? "short" : "long"); -+ break; -+ case 0x15: -+ if (len == 2) -+ dev_info(dev, "Get receive sensor\n"); -+ else -+ dev_info(dev, "Received pulse count is %d\n", -+ ((data1 << 8) | data2)); -+ break; -+ case 0xfe: -+ dev_info(dev, "Error! Hardware is likely wedged...\n"); -+ break; -+ case 0x05: -+ case 0x09: -+ case 0x0f: -+ default: -+ dev_info(dev, "Unknown command 0x%02x 0x%02x\n", -+ cmd, subcmd); -+ break; -+ } -+ break; -+ default: -+ break; -+ } -+} -+ -+static void usb_async_callback(struct urb *urb, struct pt_regs *regs) -+{ -+ struct mceusb_dev *ir; -+ int len; -+ -+ if (!urb) -+ return; -+ -+ ir = urb->context; -+ if (ir) { -+ len = urb->actual_length; -+ -+ dev_dbg(ir->dev, "callback called (status=%d len=%d)\n", -+ urb->status, len); -+ -+ if (debug) -+ mceusb_dev_printdata(ir, urb->transfer_buffer, -+ len, true); -+ } -+ -+} -+ -+/* request incoming or send outgoing usb packet - used to initialize remote */ -+static void mce_request_packet(struct mceusb_dev *ir, -+ struct usb_endpoint_descriptor *ep, -+ unsigned char *data, int size, int urb_type) -+{ -+ int res; -+ struct urb *async_urb; -+ struct device *dev = ir->dev; -+ unsigned char *async_buf; -+ -+ if (urb_type == MCEUSB_TX) { -+ async_urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (unlikely(!async_urb)) { -+ dev_err(dev, "Error, couldn't allocate urb!\n"); -+ return; -+ } -+ -+ async_buf = kzalloc(size, GFP_KERNEL); -+ if (!async_buf) { -+ dev_err(dev, "Error, couldn't allocate buf!\n"); -+ usb_free_urb(async_urb); -+ return; -+ } -+ -+ /* outbound data */ -+ usb_fill_int_urb(async_urb, ir->usbdev, -+ usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), -+ async_buf, size, (usb_complete_t) usb_async_callback, -+ ir, ep->bInterval); -+ memcpy(async_buf, data, size); -+ -+ } else if (urb_type == MCEUSB_RX) { -+ /* standard request */ -+ async_urb = ir->urb_in; -+ ir->send_flags = RECV_FLAG_IN_PROGRESS; -+ -+ } else { -+ dev_err(dev, "Error! Unknown urb type %d\n", urb_type); -+ return; -+ } -+ -+ dev_dbg(dev, "receive request called (size=%#x)\n", size); -+ -+ async_urb->transfer_buffer_length = size; -+ async_urb->dev = ir->usbdev; -+ -+ res = usb_submit_urb(async_urb, GFP_ATOMIC); -+ if (res) { -+ dev_dbg(dev, "receive request FAILED! (res=%d)\n", res); -+ return; -+ } -+ dev_dbg(dev, "receive request complete (res=%d)\n", res); -+} -+ -+static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) -+{ -+ mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX); -+} -+ -+static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) -+{ -+ mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); -+} -+ -+/* Send data out the IR blaster port(s) */ -+static int mceusb_tx_ir(void *priv, int *txbuf, u32 n) -+{ -+ struct mceusb_dev *ir = priv; -+ int i, ret = 0; -+ int count, cmdcount = 0; -+ unsigned char *cmdbuf; /* MCE command buffer */ -+ long signal_duration = 0; /* Singnal length in us */ -+ struct timeval start_time, end_time; -+ -+ do_gettimeofday(&start_time); -+ -+ count = n / sizeof(int); -+ -+ cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL); -+ if (!cmdbuf) -+ return -ENOMEM; -+ -+ /* MCE tx init header */ -+ cmdbuf[cmdcount++] = MCE_CONTROL_HEADER; -+ cmdbuf[cmdcount++] = 0x08; -+ cmdbuf[cmdcount++] = ir->tx_mask; -+ -+ /* Generate mce packet data */ -+ for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { -+ signal_duration += txbuf[i]; -+ txbuf[i] = txbuf[i] / MCE_TIME_UNIT; -+ -+ do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ -+ -+ /* Insert mce packet header every 4th entry */ -+ if ((cmdcount < MCE_CMDBUF_SIZE) && -+ (cmdcount - MCE_TX_HEADER_LENGTH) % -+ MCE_CODE_LENGTH == 0) -+ cmdbuf[cmdcount++] = MCE_PACKET_HEADER; -+ -+ /* Insert mce packet data */ -+ if (cmdcount < MCE_CMDBUF_SIZE) -+ cmdbuf[cmdcount++] = -+ (txbuf[i] < MCE_PULSE_BIT ? -+ txbuf[i] : MCE_MAX_PULSE_LENGTH) | -+ (i & 1 ? 0x00 : MCE_PULSE_BIT); -+ else { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) && -+ (txbuf[i] -= MCE_MAX_PULSE_LENGTH)); -+ } -+ -+ /* Fix packet length in last header */ -+ cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] = -+ 0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1; -+ -+ /* Check if we have room for the empty packet at the end */ -+ if (cmdcount >= MCE_CMDBUF_SIZE) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ /* All mce commands end with an empty packet (0x80) */ -+ cmdbuf[cmdcount++] = 0x80; -+ -+ /* Transmit the command to the mce device */ -+ mce_async_out(ir, cmdbuf, cmdcount); -+ -+ /* -+ * The lircd gap calculation expects the write function to -+ * wait the time it takes for the ircommand to be sent before -+ * it returns. -+ */ -+ do_gettimeofday(&end_time); -+ signal_duration -= (end_time.tv_usec - start_time.tv_usec) + -+ (end_time.tv_sec - start_time.tv_sec) * 1000000; -+ -+ /* delay with the closest number of ticks */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(usecs_to_jiffies(signal_duration)); -+ -+out: -+ kfree(cmdbuf); -+ return ret ? ret : n; -+} -+ -+/* Sets active IR outputs -- mce devices typically (all?) have two */ -+static int mceusb_set_tx_mask(void *priv, u32 mask) -+{ -+ struct mceusb_dev *ir = priv; -+ -+ if (ir->flags.tx_mask_inverted) -+ ir->tx_mask = (mask != 0x03 ? mask ^ 0x03 : mask) << 1; -+ else -+ ir->tx_mask = mask; -+ -+ return 0; -+} -+ -+/* Sets the send carrier frequency and mode */ -+static int mceusb_set_tx_carrier(void *priv, u32 carrier) -+{ -+ struct mceusb_dev *ir = priv; -+ int clk = 10000000; -+ int prescaler = 0, divisor = 0; -+ unsigned char cmdbuf[4] = { 0x9f, 0x06, 0x00, 0x00 }; -+ -+ /* Carrier has changed */ -+ if (ir->carrier != carrier) { -+ -+ if (carrier == 0) { -+ ir->carrier = carrier; -+ cmdbuf[2] = 0x01; -+ cmdbuf[3] = 0x80; -+ dev_dbg(ir->dev, "%s: disabling carrier " -+ "modulation\n", __func__); -+ mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); -+ return carrier; -+ } -+ -+ for (prescaler = 0; prescaler < 4; ++prescaler) { -+ divisor = (clk >> (2 * prescaler)) / carrier; -+ if (divisor <= 0xFF) { -+ ir->carrier = carrier; -+ cmdbuf[2] = prescaler; -+ cmdbuf[3] = divisor; -+ dev_dbg(ir->dev, "%s: requesting %u HZ " -+ "carrier\n", __func__, carrier); -+ -+ /* Transmit new carrier to mce device */ -+ mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); -+ return carrier; -+ } -+ } -+ -+ return -EINVAL; -+ -+ } -+ -+ return carrier; -+} -+ -+static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) -+{ -+ struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; -+ int i, start_index = 0; -+ u8 hdr = MCE_CONTROL_HEADER; -+ -+ /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ -+ if (ir->flags.microsoft_gen1) -+ start_index = 2; -+ -+ for (i = start_index; i < buf_len;) { -+ if (ir->rem == 0) { -+ /* decode mce packets of the form (84),AA,BB,CC,DD */ -+ /* IR data packets can span USB messages - rem */ -+ hdr = ir->buf_in[i]; -+ ir->rem = (hdr & MCE_PACKET_LENGTH_MASK); -+ ir->cmd = (hdr & ~MCE_PACKET_LENGTH_MASK); -+ dev_dbg(ir->dev, "New data. rem: 0x%02x, cmd: 0x%02x\n", -+ ir->rem, ir->cmd); -+ i++; -+ } -+ -+ /* don't process MCE commands */ -+ if (hdr == MCE_CONTROL_HEADER || hdr == 0xff) { -+ ir->rem = 0; -+ return; -+ } -+ -+ for (; (ir->rem > 0) && (i < buf_len); i++) { -+ ir->rem--; -+ -+ rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); -+ rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) -+ * MCE_TIME_UNIT * 1000; -+ -+ if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) { -+ if (ir->rawir.pulse == rawir.pulse) -+ ir->rawir.duration += rawir.duration; -+ else { -+ ir->rawir.duration = rawir.duration; -+ ir->rawir.pulse = rawir.pulse; -+ } -+ continue; -+ } -+ rawir.duration += ir->rawir.duration; -+ ir->rawir.duration = 0; -+ ir->rawir.pulse = rawir.pulse; -+ -+ dev_dbg(ir->dev, "Storing %s with duration %d\n", -+ rawir.pulse ? "pulse" : "space", -+ rawir.duration); -+ -+ ir_raw_event_store(ir->idev, &rawir); -+ } -+ -+ if (ir->buf_in[i] == 0x80 || ir->buf_in[i] == 0x9f) -+ ir->rem = 0; -+ -+ dev_dbg(ir->dev, "calling ir_raw_event_handle\n"); -+ ir_raw_event_handle(ir->idev); -+ } -+} -+ -+static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) -+{ -+ struct mceusb_dev *ir; -+ int buf_len; -+ -+ if (!urb) -+ return; -+ -+ ir = urb->context; -+ if (!ir) { -+ usb_unlink_urb(urb); -+ return; -+ } -+ -+ buf_len = urb->actual_length; -+ -+ if (debug) -+ mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len, false); -+ -+ if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { -+ ir->send_flags = SEND_FLAG_COMPLETE; -+ dev_dbg(&ir->irdev->dev, "setup answer received %d bytes\n", -+ buf_len); -+ } -+ -+ switch (urb->status) { -+ /* success */ -+ case 0: -+ mceusb_process_ir_data(ir, buf_len); -+ break; -+ -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ usb_unlink_urb(urb); -+ return; -+ -+ case -EPIPE: -+ default: -+ break; -+ } -+ -+ usb_submit_urb(urb, GFP_ATOMIC); -+} -+ -+static void mceusb_gen1_init(struct mceusb_dev *ir) -+{ -+ int ret; -+ int maxp = ir->len_in; -+ struct device *dev = ir->dev; -+ char *data; -+ -+ data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL); -+ if (!data) { -+ dev_err(dev, "%s: memory allocation failed!\n", __func__); -+ return; -+ } -+ -+ /* -+ * This is a strange one. Windows issues a set address to the device -+ * on the receive control pipe and expect a certain value pair back -+ */ -+ ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), -+ USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, -+ data, USB_CTRL_MSG_SZ, HZ * 3); -+ dev_dbg(dev, "%s - ret = %d\n", __func__, ret); -+ dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", -+ __func__, data[0], data[1]); -+ -+ /* set feature: bit rate 38400 bps */ -+ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), -+ USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, -+ 0xc04e, 0x0000, NULL, 0, HZ * 3); -+ -+ dev_dbg(dev, "%s - ret = %d\n", __func__, ret); -+ -+ /* bRequest 4: set char length to 8 bits */ -+ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), -+ 4, USB_TYPE_VENDOR, -+ 0x0808, 0x0000, NULL, 0, HZ * 3); -+ dev_dbg(dev, "%s - retB = %d\n", __func__, ret); -+ -+ /* bRequest 2: set handshaking to use DTR/DSR */ -+ ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), -+ 2, USB_TYPE_VENDOR, -+ 0x0000, 0x0100, NULL, 0, HZ * 3); -+ dev_dbg(dev, "%s - retC = %d\n", __func__, ret); -+ -+ /* device reset */ -+ mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); -+ mce_sync_in(ir, NULL, maxp); -+ -+ /* get hw/sw revision? */ -+ mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); -+ mce_sync_in(ir, NULL, maxp); -+ -+ kfree(data); -+}; -+ -+static void mceusb_gen2_init(struct mceusb_dev *ir) -+{ -+ int maxp = ir->len_in; -+ -+ /* device reset */ -+ mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); -+ mce_sync_in(ir, NULL, maxp); -+ -+ /* get hw/sw revision? */ -+ mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); -+ mce_sync_in(ir, NULL, maxp); -+ -+ /* unknown what the next two actually return... */ -+ mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); -+ mce_sync_in(ir, NULL, maxp); -+ mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); -+ mce_sync_in(ir, NULL, maxp); -+} -+ -+static void mceusb_get_parameters(struct mceusb_dev *ir) -+{ -+ int maxp = ir->len_in; -+ -+ /* get the carrier and frequency */ -+ mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); -+ mce_sync_in(ir, NULL, maxp); -+ -+ /* get the transmitter bitmask */ -+ mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); -+ mce_sync_in(ir, NULL, maxp); -+ -+ /* get receiver timeout value */ -+ mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); -+ mce_sync_in(ir, NULL, maxp); -+ -+ /* get receiver sensor setting */ -+ mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); -+ mce_sync_in(ir, NULL, maxp); -+} -+ -+static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) -+{ -+ struct input_dev *idev; -+ struct ir_dev_props *props; -+ struct ir_input_dev *irdev; -+ struct device *dev = ir->dev; -+ int ret = -ENODEV; -+ -+ idev = input_allocate_device(); -+ if (!idev) { -+ dev_err(dev, "remote input dev allocation failed\n"); -+ goto idev_alloc_failed; -+ } -+ -+ ret = -ENOMEM; -+ props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); -+ if (!props) { -+ dev_err(dev, "remote ir dev props allocation failed\n"); -+ goto props_alloc_failed; -+ } -+ -+ irdev = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL); -+ if (!irdev) { -+ dev_err(dev, "remote ir input dev allocation failed\n"); -+ goto ir_dev_alloc_failed; -+ } -+ -+ snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome " -+ "Infrared Remote Transceiver (%04x:%04x)", -+ le16_to_cpu(ir->usbdev->descriptor.idVendor), -+ le16_to_cpu(ir->usbdev->descriptor.idProduct)); -+ -+ idev->name = ir->name; -+ usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys)); -+ strlcat(ir->phys, "/input0", sizeof(ir->phys)); -+ idev->phys = ir->phys; -+ -+ props->priv = ir; -+ props->driver_type = RC_DRIVER_IR_RAW; -+ props->allowed_protos = IR_TYPE_ALL; -+ props->s_tx_mask = mceusb_set_tx_mask; -+ props->s_tx_carrier = mceusb_set_tx_carrier; -+ props->tx_ir = mceusb_tx_ir; -+ -+ ir->props = props; -+ ir->irdev = irdev; -+ -+ input_set_drvdata(idev, irdev); -+ -+ ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME); -+ if (ret < 0) { -+ dev_err(dev, "remote input device register failed\n"); -+ goto irdev_failed; -+ } -+ -+ return idev; -+ -+irdev_failed: -+ kfree(irdev); -+ir_dev_alloc_failed: -+ kfree(props); -+props_alloc_failed: -+ input_free_device(idev); -+idev_alloc_failed: -+ return NULL; -+} -+ -+static int __devinit mceusb_dev_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct usb_host_interface *idesc; -+ struct usb_endpoint_descriptor *ep = NULL; -+ struct usb_endpoint_descriptor *ep_in = NULL; -+ struct usb_endpoint_descriptor *ep_out = NULL; -+ struct usb_host_config *config; -+ struct mceusb_dev *ir = NULL; -+ int pipe, maxp, i; -+ char buf[63], name[128] = ""; -+ bool is_gen3; -+ bool is_microsoft_gen1; -+ bool tx_mask_inverted; -+ -+ dev_dbg(&intf->dev, ": %s called\n", __func__); -+ -+ config = dev->actconfig; -+ idesc = intf->cur_altsetting; -+ -+ is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0; -+ is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0; -+ tx_mask_inverted = usb_match_id(intf, std_tx_mask_list) ? 0 : 1; -+ -+ /* step through the endpoints to find first bulk in and out endpoint */ -+ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { -+ ep = &idesc->endpoint[i].desc; -+ -+ if ((ep_in == NULL) -+ && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) -+ == USB_DIR_IN) -+ && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) -+ == USB_ENDPOINT_XFER_BULK) -+ || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) -+ == USB_ENDPOINT_XFER_INT))) { -+ -+ ep_in = ep; -+ ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; -+ ep_in->bInterval = 1; -+ dev_dbg(&intf->dev, ": acceptable inbound endpoint " -+ "found\n"); -+ } -+ -+ if ((ep_out == NULL) -+ && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) -+ == USB_DIR_OUT) -+ && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) -+ == USB_ENDPOINT_XFER_BULK) -+ || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) -+ == USB_ENDPOINT_XFER_INT))) { -+ -+ ep_out = ep; -+ ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; -+ ep_out->bInterval = 1; -+ dev_dbg(&intf->dev, ": acceptable outbound endpoint " -+ "found\n"); -+ } -+ } -+ if (ep_in == NULL) { -+ dev_dbg(&intf->dev, ": inbound and/or endpoint not found\n"); -+ return -ENODEV; -+ } -+ -+ pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); -+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); -+ -+ ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); -+ if (!ir) -+ goto mem_alloc_fail; -+ -+ ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); -+ if (!ir->buf_in) -+ goto buf_in_alloc_fail; -+ -+ ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); -+ if (!ir->urb_in) -+ goto urb_in_alloc_fail; -+ -+ ir->usbdev = dev; -+ ir->dev = &intf->dev; -+ ir->len_in = maxp; -+ ir->flags.microsoft_gen1 = is_microsoft_gen1; -+ ir->flags.tx_mask_inverted = tx_mask_inverted; -+ -+ /* Saving usb interface data for use by the transmitter routine */ -+ ir->usb_ep_in = ep_in; -+ ir->usb_ep_out = ep_out; -+ -+ if (dev->descriptor.iManufacturer -+ && usb_string(dev, dev->descriptor.iManufacturer, -+ buf, sizeof(buf)) > 0) -+ strlcpy(name, buf, sizeof(name)); -+ if (dev->descriptor.iProduct -+ && usb_string(dev, dev->descriptor.iProduct, -+ buf, sizeof(buf)) > 0) -+ snprintf(name + strlen(name), sizeof(name) - strlen(name), -+ " %s", buf); -+ -+ ir->idev = mceusb_init_input_dev(ir); -+ if (!ir->idev) -+ goto input_dev_fail; -+ -+ /* flush buffers on the device */ -+ mce_sync_in(ir, NULL, maxp); -+ mce_sync_in(ir, NULL, maxp); -+ -+ /* wire up inbound data handler */ -+ usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, -+ maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); -+ ir->urb_in->transfer_dma = ir->dma_in; -+ ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ /* initialize device */ -+ if (ir->flags.microsoft_gen1) -+ mceusb_gen1_init(ir); -+ else if (!is_gen3) -+ mceusb_gen2_init(ir); -+ -+ mceusb_get_parameters(ir); -+ -+ mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK); -+ -+ usb_set_intfdata(intf, ir); -+ -+ dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name, -+ dev->bus->busnum, dev->devnum); -+ -+ return 0; -+ -+ /* Error-handling path */ -+input_dev_fail: -+ usb_free_urb(ir->urb_in); -+urb_in_alloc_fail: -+ usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in); -+buf_in_alloc_fail: -+ kfree(ir); -+mem_alloc_fail: -+ dev_err(&intf->dev, "%s: device setup failed!\n", __func__); -+ -+ return -ENOMEM; -+} -+ -+ -+static void __devexit mceusb_dev_disconnect(struct usb_interface *intf) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct mceusb_dev *ir = usb_get_intfdata(intf); -+ -+ usb_set_intfdata(intf, NULL); -+ -+ if (!ir) -+ return; -+ -+ ir->usbdev = NULL; -+ ir_input_unregister(ir->idev); -+ usb_kill_urb(ir->urb_in); -+ usb_free_urb(ir->urb_in); -+ usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); -+ -+ kfree(ir); -+} -+ -+static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message) -+{ -+ struct mceusb_dev *ir = usb_get_intfdata(intf); -+ dev_info(ir->dev, "suspend\n"); -+ usb_kill_urb(ir->urb_in); -+ return 0; -+} -+ -+static int mceusb_dev_resume(struct usb_interface *intf) -+{ -+ struct mceusb_dev *ir = usb_get_intfdata(intf); -+ dev_info(ir->dev, "resume\n"); -+ if (usb_submit_urb(ir->urb_in, GFP_ATOMIC)) -+ return -EIO; -+ return 0; -+} -+ -+static struct usb_driver mceusb_dev_driver = { -+ .name = DRIVER_NAME, -+ .probe = mceusb_dev_probe, -+ .disconnect = mceusb_dev_disconnect, -+ .suspend = mceusb_dev_suspend, -+ .resume = mceusb_dev_resume, -+ .reset_resume = mceusb_dev_resume, -+ .id_table = mceusb_dev_table -+}; -+ -+static int __init mceusb_dev_init(void) -+{ -+ int ret; -+ -+ ret = usb_register(&mceusb_dev_driver); -+ if (ret < 0) -+ printk(KERN_ERR DRIVER_NAME -+ ": usb register failed, result = %d\n", ret); -+ -+ return ret; -+} -+ -+static void __exit mceusb_dev_exit(void) -+{ -+ usb_deregister(&mceusb_dev_driver); -+} -+ -+module_init(mceusb_dev_init); -+module_exit(mceusb_dev_exit); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(usb, mceusb_dev_table); -+ -+module_param(debug, bool, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Debug enabled or not"); -diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c -index b2e1545..7955e49 100644 ---- a/drivers/media/common/tuners/tda18271-fe.c -+++ b/drivers/media/common/tuners/tda18271-fe.c -@@ -1249,7 +1249,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, - struct tda18271_config *cfg) - { - struct tda18271_priv *priv = NULL; -- int instance; -+ int instance, ret; - - mutex_lock(&tda18271_list_mutex); - -@@ -1268,10 +1268,12 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, - priv->cal_initialized = false; - mutex_init(&priv->lock); - -- if (tda_fail(tda18271_get_id(fe))) -+ ret = tda18271_get_id(fe); -+ if (tda_fail(ret)) - goto fail; - -- if (tda_fail(tda18271_assign_map_layout(fe))) -+ ret = tda18271_assign_map_layout(fe); -+ if (tda_fail(ret)) - goto fail; - - mutex_lock(&priv->lock); -diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig -index f7b72a3..decdeda 100644 ---- a/drivers/media/dvb/mantis/Kconfig -+++ b/drivers/media/dvb/mantis/Kconfig -@@ -10,9 +10,15 @@ config MANTIS_CORE - config DVB_MANTIS - tristate "MANTIS based cards" - depends on MANTIS_CORE && DVB_CORE && PCI && I2C -- select DVB_MB86A16 -- select DVB_ZL10353 -- select DVB_STV0299 -+ select DVB_MB86A16 if !DVB_FE_CUSTOMISE -+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE -+ select DVB_STV0299 if !DVB_FE_CUSTOMISE -+ select DVB_LNBP21 if !DVB_FE_CUSTOMISE -+ select DVB_STB0899 if !DVB_FE_CUSTOMISE -+ select DVB_STB6100 if !DVB_FE_CUSTOMISE -+ select DVB_TDA665x if !DVB_FE_CUSTOMISE -+ select DVB_TDA10021 if !DVB_FE_CUSTOMISE -+ select DVB_TDA10023 if !DVB_FE_CUSTOMISE - select DVB_PLL - help - Support for PCI cards based on the Mantis PCI bridge. -@@ -23,7 +29,7 @@ config DVB_MANTIS - config DVB_HOPPER - tristate "HOPPER based cards" - depends on MANTIS_CORE && DVB_CORE && PCI && I2C -- select DVB_ZL10353 -+ select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_PLL - help - Support for PCI cards based on the Hopper PCI bridge. -diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c -index 3d4e466..a99489b 100644 ---- a/drivers/media/dvb/mantis/mantis_input.c -+++ b/drivers/media/dvb/mantis/mantis_input.c -@@ -19,7 +19,7 @@ - */ - - #include --#include -+#include - #include - - #include "dmxdev.h" -@@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(ir_mantis); - int mantis_input_init(struct mantis_pci *mantis) - { - struct input_dev *rc; -- struct ir_input_state rc_state; - char name[80], dev[80]; - int err; - -@@ -120,8 +119,6 @@ int mantis_input_init(struct mantis_pci *mantis) - rc->name = name; - rc->phys = dev; - -- ir_input_init(rc, &rc_state, IR_TYPE_OTHER); -- - rc->id.bustype = BUS_PCI; - rc->id.vendor = mantis->vendor_id; - rc->id.product = mantis->device_id; -diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c -index d639186..2014dae 100644 ---- a/drivers/media/video/cx23885/cx23885-cards.c -+++ b/drivers/media/video/cx23885/cx23885-cards.c -@@ -408,10 +408,18 @@ struct cx23885_subid cx23885_subids[] = { - .card = CX23885_BOARD_HAUPPAUGE_HVR1275, - }, { - .subvendor = 0x0070, -+ .subdevice = 0x221d, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1275, -+ }, { -+ .subvendor = 0x0070, - .subdevice = 0x2251, - .card = CX23885_BOARD_HAUPPAUGE_HVR1255, - }, { - .subvendor = 0x0070, -+ .subdevice = 0x2259, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1255, -+ }, { -+ .subvendor = 0x0070, - .subdevice = 0x2291, - .card = CX23885_BOARD_HAUPPAUGE_HVR1210, - }, { -@@ -419,6 +427,38 @@ struct cx23885_subid cx23885_subids[] = { - .subdevice = 0x2295, - .card = CX23885_BOARD_HAUPPAUGE_HVR1210, - }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x2299, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1210, -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x229d, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x22f0, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1210, -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x22f1, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1255, -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x22f2, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1275, -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x22f3, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x22f4, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1210, -+ }, { -+ .subvendor = 0x0070, -+ .subdevice = 0x22f5, -+ .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ -+ }, { - .subvendor = 0x14f1, - .subdevice = 0x8651, - .card = CX23885_BOARD_MYGICA_X8506, -diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c -index 0dde57e..ff76f64 100644 ---- a/drivers/media/video/cx23885/cx23885-core.c -+++ b/drivers/media/video/cx23885/cx23885-core.c -@@ -1142,7 +1142,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) - - BUG_ON(in_interrupt()); - videobuf_waiton(&buf->vb, 0, 0); -- videobuf_dma_unmap(q, dma); -+ videobuf_dma_unmap(q->dev, dma); - videobuf_dma_free(dma); - btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -@@ -1953,8 +1953,12 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, - goto fail_irq; - } - -- err = request_irq(pci_dev->irq, cx23885_irq, -- IRQF_SHARED | IRQF_DISABLED, dev->name, dev); -+ if (!pci_enable_msi(pci_dev)) -+ err = request_irq(pci_dev->irq, cx23885_irq, -+ IRQF_DISABLED, dev->name, dev); -+ else -+ err = request_irq(pci_dev->irq, cx23885_irq, -+ IRQF_SHARED | IRQF_DISABLED, dev->name, dev); - if (err < 0) { - printk(KERN_ERR "%s: can't get IRQ %d\n", - dev->name, pci_dev->irq); -@@ -2000,6 +2004,7 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) - - /* unregister stuff */ - free_irq(pci_dev->irq, dev); -+ pci_disable_msi(pci_dev); - - cx23885_dev_unregister(dev); - v4l2_device_unregister(v4l2_dev); -diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c -index 0a199d7..3d70af2 100644 ---- a/drivers/media/video/cx23885/cx23885-dvb.c -+++ b/drivers/media/video/cx23885/cx23885-dvb.c -@@ -991,7 +991,7 @@ static int dvb_register(struct cx23885_tsport *port) - ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, - &dev->pci->dev, adapter_nr, 0, - cx23885_dvb_fe_ioctl_override); -- if (!ret) -+ if (ret) - return ret; - - /* init CI & MAC */ -diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c -index 5de6ba9..d0b1613 100644 ---- a/drivers/media/video/cx23885/cx23885-input.c -+++ b/drivers/media/video/cx23885/cx23885-input.c -@@ -37,161 +37,55 @@ - - #include - #include --#include -+#include - #include - - #include "cx23885.h" - --#define RC5_BITS 14 --#define RC5_HALF_BITS (2*RC5_BITS) --#define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1) -- --#define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */ --#define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */ -- --#define RC5_EXTENDED_COMMAND_OFFSET 64 -- - #define MODULE_NAME "cx23885" - --static inline unsigned int rc5_command(u32 rc5_baseband) -+static void convert_measurement(u32 x, struct ir_raw_event *y) - { -- return RC5_INSTR(rc5_baseband) + -- ((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED) -- ? RC5_EXTENDED_COMMAND_OFFSET : 0); --} -- --static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev) --{ -- struct card_ir *ir_input = dev->ir_input; -- unsigned int code, command; -- u32 rc5; -- -- /* Ignore codes that are too short to be valid RC-5 */ -- if (ir_input->last_bit < (RC5_HALF_BITS - 1)) -- return; -- -- /* The library has the manchester coding backwards; XOR to adapt. */ -- code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK; -- rc5 = ir_rc5_decode(code); -- -- switch (RC5_START(rc5)) { -- case RC5_START_BITS_NORMAL: -- break; -- case RC5_START_BITS_EXTENDED: -- /* Don't allow if the remote only emits standard commands */ -- if (ir_input->start == RC5_START_BITS_NORMAL) -- return; -- break; -- default: -+ if (x == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { -+ y->pulse = false; -+ y->duration = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; - return; - } - -- if (ir_input->addr != RC5_ADDR(rc5)) -- return; -- -- /* Don't generate a keypress for RC-5 auto-repeated keypresses */ -- command = rc5_command(rc5); -- if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) || -- command != rc5_command(ir_input->last_rc5) || -- /* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */ -- RC5_START(ir_input->last_rc5) == 0) { -- /* This keypress is differnet: not an auto repeat */ -- ir_input_nokey(ir_input->dev, &ir_input->ir); -- ir_input_keydown(ir_input->dev, &ir_input->ir, command); -- } -- ir_input->last_rc5 = rc5; -- -- /* Schedule when we should do the key up event: ir_input_nokey() */ -- mod_timer(&ir_input->timer_keyup, -- jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout)); -+ y->pulse = (x & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? true : false; -+ y->duration = x & V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; - } - --static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev, -- u32 ns_pulse) -+static void cx23885_input_process_measurements(struct cx23885_dev *dev, -+ bool overrun) - { -- const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */ -- struct card_ir *ir_input = dev->ir_input; -- int i, level, quarterbits, halfbits; -- -- if (!ir_input->active) { -- ir_input->active = 1; -- /* assume an initial space that we may not detect or measure */ -- ir_input->code = 0; -- ir_input->last_bit = 0; -- } -+ struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir; -+ struct ir_raw_event kernel_ir_event; - -- if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { -- ir_input->last_bit++; /* Account for the final space */ -- ir_input->active = 0; -- cx23885_input_process_raw_rc5(dev); -- return; -- } -- -- level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0; -- -- /* Skip any leading space to sync to the start bit */ -- if (ir_input->last_bit == 0 && level == 0) -- return; -- -- /* -- * With valid RC-5 we can get up to two consecutive half-bits in a -- * single pulse measurment. Experiments have shown that the duration -- * of a half-bit can vary. Make sure we always end up with an even -- * number of quarter bits at the same level (mark or space). -- */ -- ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; -- quarterbits = ns_pulse / rc5_quarterbit_ns; -- if (quarterbits & 1) -- quarterbits++; -- halfbits = quarterbits / 2; -- -- for (i = 0; i < halfbits; i++) { -- ir_input->last_bit++; -- ir_input->code |= (level << ir_input->last_bit); -- -- if (ir_input->last_bit >= RC5_HALF_BITS-1) { -- ir_input->active = 0; -- cx23885_input_process_raw_rc5(dev); -- /* -- * If level is 1, a leading mark is invalid for RC5. -- * If level is 0, we scan past extra intial space. -- * Either way we don't want to reactivate collecting -- * marks or spaces here with any left over half-bits. -- */ -- break; -- } -- } --} -- --static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev, -- bool add_eom) --{ -- struct card_ir *ir_input = dev->ir_input; -- struct ir_input_state *ir_input_state = &ir_input->ir; -- -- u32 ns_pulse[RC5_HALF_BITS+1]; -- ssize_t num = 0; -+ u32 sd_ir_data[64]; -+ ssize_t num; - int count, i; -+ bool handle = false; - - do { -- v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse, -- sizeof(ns_pulse), &num); -+ num = 0; -+ v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) sd_ir_data, -+ sizeof(sd_ir_data), &num); - - count = num / sizeof(u32); - -- /* Append an end of Rx seq, if the caller requested */ -- if (add_eom && count < ARRAY_SIZE(ns_pulse)) { -- ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; -- count++; -+ for (i = 0; i < count; i++) { -+ convert_measurement(sd_ir_data[i], &kernel_ir_event); -+ ir_raw_event_store(kernel_ir->inp_dev, -+ &kernel_ir_event); -+ handle = true; - } -- -- /* Just drain the Rx FIFO, if we're called, but not RC-5 */ -- if (ir_input_state->ir_type != IR_TYPE_RC5) -- continue; -- -- for (i = 0; i < count; i++) -- cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]); - } while (num != 0); -+ -+ if (overrun) -+ ir_raw_event_reset(kernel_ir->inp_dev); -+ else if (handle) -+ ir_raw_event_handle(kernel_ir->inp_dev); - } - - void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) -@@ -230,7 +124,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) - } - - if (data_available) -- cx23885_input_process_pulse_widths_rc5(dev, overrun); -+ cx23885_input_process_measurements(dev, overrun); - - if (overrun) { - /* If there was a FIFO overrun, clear & restart the device */ -@@ -241,34 +135,15 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) - } - } - --static void cx23885_input_ir_start(struct cx23885_dev *dev) -+static int cx23885_input_ir_start(struct cx23885_dev *dev) - { -- struct card_ir *ir_input = dev->ir_input; -- struct ir_input_state *ir_input_state = &ir_input->ir; - struct v4l2_subdev_ir_parameters params; - - if (dev->sd_ir == NULL) -- return; -+ return -ENODEV; - - atomic_set(&dev->ir_input_stopping, 0); - -- /* keyup timer set up, if needed */ -- switch (dev->board) { -- case CX23885_BOARD_HAUPPAUGE_HVR1850: -- case CX23885_BOARD_HAUPPAUGE_HVR1290: -- setup_timer(&ir_input->timer_keyup, -- ir_rc5_timer_keyup, /* Not actually RC-5 specific */ -- (unsigned long) ir_input); -- if (ir_input_state->ir_type == IR_TYPE_RC5) { -- /* -- * RC-5 repeats a held key every -- * 64 bits * (2 * 32/36000) sec/bit = 113.778 ms -- */ -- ir_input->rc5_key_timeout = 115; -- } -- break; -- } -- - v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); - switch (dev->board) { - case CX23885_BOARD_HAUPPAUGE_HVR1850: -@@ -299,11 +174,21 @@ static void cx23885_input_ir_start(struct cx23885_dev *dev) - break; - } - v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); -+ return 0; -+} -+ -+static int cx23885_input_ir_open(void *priv) -+{ -+ struct cx23885_kernel_ir *kernel_ir = priv; -+ -+ if (kernel_ir->cx == NULL) -+ return -ENODEV; -+ -+ return cx23885_input_ir_start(kernel_ir->cx); - } - - static void cx23885_input_ir_stop(struct cx23885_dev *dev) - { -- struct card_ir *ir_input = dev->ir_input; - struct v4l2_subdev_ir_parameters params; - - if (dev->sd_ir == NULL) -@@ -327,21 +212,26 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev) - } - - flush_scheduled_work(); -+} - -- switch (dev->board) { -- case CX23885_BOARD_HAUPPAUGE_HVR1850: -- case CX23885_BOARD_HAUPPAUGE_HVR1290: -- del_timer_sync(&ir_input->timer_keyup); -- break; -- } -+static void cx23885_input_ir_close(void *priv) -+{ -+ struct cx23885_kernel_ir *kernel_ir = priv; -+ -+ if (kernel_ir->cx != NULL) -+ cx23885_input_ir_stop(kernel_ir->cx); - } - - int cx23885_input_init(struct cx23885_dev *dev) - { -- struct card_ir *ir; -- struct input_dev *input_dev; -- char *ir_codes = NULL; -- int ir_type, ir_addr, ir_start; -+ struct cx23885_kernel_ir *kernel_ir; -+ struct input_dev *inp_dev; -+ struct ir_dev_props *props; -+ -+ char *rc_map; -+ enum rc_driver_type driver_type; -+ unsigned long allowed_protos; -+ - int ret; - - /* -@@ -354,53 +244,59 @@ int cx23885_input_init(struct cx23885_dev *dev) - switch (dev->board) { - case CX23885_BOARD_HAUPPAUGE_HVR1850: - case CX23885_BOARD_HAUPPAUGE_HVR1290: -- /* Parameters for the grey Hauppauge remote for the HVR-1850 */ -- ir_codes = RC_MAP_HAUPPAUGE_NEW; -- ir_type = IR_TYPE_RC5; -- ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ -- ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ -+ /* Integrated CX23888 IR controller */ -+ driver_type = RC_DRIVER_IR_RAW; -+ allowed_protos = IR_TYPE_ALL; -+ /* The grey Hauppauge RC-5 remote */ -+ rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; - break; -- } -- if (ir_codes == NULL) -+ default: - return -ENODEV; -- -- ir = kzalloc(sizeof(*ir), GFP_KERNEL); -- input_dev = input_allocate_device(); -- if (!ir || !input_dev) { -- ret = -ENOMEM; -- goto err_out_free; - } - -- ir->dev = input_dev; -- ir->addr = ir_addr; -- ir->start = ir_start; -+ /* cx23885 board instance kernel IR state */ -+ kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL); -+ if (kernel_ir == NULL) -+ return -ENOMEM; - -- /* init input device */ -- snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)", -- cx23885_boards[dev->board].name); -- snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); -+ kernel_ir->cx = dev; -+ kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)", -+ cx23885_boards[dev->board].name); -+ kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0", -+ pci_name(dev->pci)); - -- ret = ir_input_init(input_dev, &ir->ir, ir_type); -- if (ret < 0) -+ /* input device */ -+ inp_dev = input_allocate_device(); -+ if (inp_dev == NULL) { -+ ret = -ENOMEM; - goto err_out_free; -+ } - -- input_dev->name = ir->name; -- input_dev->phys = ir->phys; -- input_dev->id.bustype = BUS_PCI; -- input_dev->id.version = 1; -+ kernel_ir->inp_dev = inp_dev; -+ inp_dev->name = kernel_ir->name; -+ inp_dev->phys = kernel_ir->phys; -+ inp_dev->id.bustype = BUS_PCI; -+ inp_dev->id.version = 1; - if (dev->pci->subsystem_vendor) { -- input_dev->id.vendor = dev->pci->subsystem_vendor; -- input_dev->id.product = dev->pci->subsystem_device; -+ inp_dev->id.vendor = dev->pci->subsystem_vendor; -+ inp_dev->id.product = dev->pci->subsystem_device; - } else { -- input_dev->id.vendor = dev->pci->vendor; -- input_dev->id.product = dev->pci->device; -+ inp_dev->id.vendor = dev->pci->vendor; -+ inp_dev->id.product = dev->pci->device; - } -- input_dev->dev.parent = &dev->pci->dev; -- -- dev->ir_input = ir; -- cx23885_input_ir_start(dev); -- -- ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); -+ inp_dev->dev.parent = &dev->pci->dev; -+ -+ /* kernel ir device properties */ -+ props = &kernel_ir->props; -+ props->driver_type = driver_type; -+ props->allowed_protos = allowed_protos; -+ props->priv = kernel_ir; -+ props->open = cx23885_input_ir_open; -+ props->close = cx23885_input_ir_close; -+ -+ /* Go */ -+ dev->kernel_ir = kernel_ir; -+ ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME); - if (ret) - goto err_out_stop; - -@@ -408,9 +304,12 @@ int cx23885_input_init(struct cx23885_dev *dev) - - err_out_stop: - cx23885_input_ir_stop(dev); -- dev->ir_input = NULL; -+ dev->kernel_ir = NULL; -+ /* TODO: double check clean-up of kernel_ir->inp_dev */ - err_out_free: -- kfree(ir); -+ kfree(kernel_ir->phys); -+ kfree(kernel_ir->name); -+ kfree(kernel_ir); - return ret; - } - -@@ -419,9 +318,11 @@ void cx23885_input_fini(struct cx23885_dev *dev) - /* Always stop the IR hardware from generating interrupts */ - cx23885_input_ir_stop(dev); - -- if (dev->ir_input == NULL) -+ if (dev->kernel_ir == NULL) - return; -- ir_input_unregister(dev->ir_input->dev); -- kfree(dev->ir_input); -- dev->ir_input = NULL; -+ ir_input_unregister(dev->kernel_ir->inp_dev); -+ kfree(dev->kernel_ir->phys); -+ kfree(dev->kernel_ir->name); -+ kfree(dev->kernel_ir); -+ dev->kernel_ir = NULL; - } -diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c -index 9a677eb..6ceabd4 100644 ---- a/drivers/media/video/cx23885/cx23885-ir.c -+++ b/drivers/media/video/cx23885/cx23885-ir.c -@@ -53,7 +53,7 @@ void cx23885_ir_rx_work_handler(struct work_struct *work) - if (events == 0) - return; - -- if (dev->ir_input) -+ if (dev->kernel_ir) - cx23885_input_rx_work_handler(dev, events); - } - -diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h -index 8d6a55e..a33f2b7 100644 ---- a/drivers/media/video/cx23885/cx23885.h -+++ b/drivers/media/video/cx23885/cx23885.h -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include "btcx-risc.h" - #include "cx23885-reg.h" -@@ -304,6 +305,15 @@ struct cx23885_tsport { - void *port_priv; - }; - -+struct cx23885_kernel_ir { -+ struct cx23885_dev *cx; -+ char *name; -+ char *phys; -+ -+ struct input_dev *inp_dev; -+ struct ir_dev_props props; -+}; -+ - struct cx23885_dev { - atomic_t refcount; - struct v4l2_device v4l2_dev; -@@ -363,7 +373,7 @@ struct cx23885_dev { - struct work_struct ir_tx_work; - unsigned long ir_tx_notifications; - -- struct card_ir *ir_input; -+ struct cx23885_kernel_ir *kernel_ir; - atomic_t ir_input_stopping; - - /* V4l */ -diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c -index 2918a6e..e8416b7 100644 ---- a/drivers/media/video/cx88/cx88-cards.c -+++ b/drivers/media/video/cx88/cx88-cards.c -@@ -45,6 +45,10 @@ static unsigned int latency = UNSET; - module_param(latency,int,0444); - MODULE_PARM_DESC(latency,"pci latency timer"); - -+static int disable_ir; -+module_param(disable_ir, int, 0444); -+MODULE_PARM_DESC(latency, "Disable IR support"); -+ - #define info_printk(core, fmt, arg...) \ - printk(KERN_INFO "%s: " fmt, core->name , ## arg) - -@@ -3498,7 +3502,10 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) - } - - cx88_card_setup(core); -- cx88_ir_init(core, pci); -+ if (!disable_ir) { -+ cx88_i2c_init_ir(core); -+ cx88_ir_init(core, pci); -+ } - - return core; - } -diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c -index fb39f11..375ad53 100644 ---- a/drivers/media/video/cx88/cx88-i2c.c -+++ b/drivers/media/video/cx88/cx88-i2c.c -@@ -181,6 +181,11 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) - } else - printk("%s: i2c register FAILED\n", core->name); - -+ return core->i2c_rc; -+} -+ -+void cx88_i2c_init_ir(struct cx88_core *core) -+{ - /* Instantiate the IR receiver device, if present */ - if (0 == core->i2c_rc) { - struct i2c_board_info info; -@@ -207,7 +212,6 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) - } - } - } -- return core->i2c_rc; - } - - /* ----------------------------------------------------------------------- */ -diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c -index e185289..eccc5e4 100644 ---- a/drivers/media/video/cx88/cx88-input.c -+++ b/drivers/media/video/cx88/cx88-input.c -@@ -30,6 +30,7 @@ - #include - - #include "cx88.h" -+#include - #include - - #define MODULE_NAME "cx88xx" -@@ -39,8 +40,8 @@ - struct cx88_IR { - struct cx88_core *core; - struct input_dev *input; -- struct ir_input_state ir; - struct ir_dev_props props; -+ u64 ir_type; - - int users; - -@@ -51,7 +52,6 @@ struct cx88_IR { - u32 sampling; - u32 samples[16]; - int scount; -- unsigned long release; - - /* poll external decoder */ - int polling; -@@ -125,29 +125,21 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) - - data = (data << 4) | ((gpio_key & 0xf0) >> 4); - -- ir_input_keydown(ir->input, &ir->ir, data); -- ir_input_nokey(ir->input, &ir->ir); -+ ir_keydown(ir->input, data, 0); - - } else if (ir->mask_keydown) { - /* bit set on keydown */ -- if (gpio & ir->mask_keydown) { -- ir_input_keydown(ir->input, &ir->ir, data); -- } else { -- ir_input_nokey(ir->input, &ir->ir); -- } -+ if (gpio & ir->mask_keydown) -+ ir_keydown(ir->input, data, 0); - - } else if (ir->mask_keyup) { - /* bit cleared on keydown */ -- if (0 == (gpio & ir->mask_keyup)) { -- ir_input_keydown(ir->input, &ir->ir, data); -- } else { -- ir_input_nokey(ir->input, &ir->ir); -- } -+ if (0 == (gpio & ir->mask_keyup)) -+ ir_keydown(ir->input, data, 0); - - } else { - /* can't distinguish keydown/up :-/ */ -- ir_input_keydown(ir->input, &ir->ir, data); -- ir_input_nokey(ir->input, &ir->ir); -+ ir_keydown(ir->input, data, 0); - } - } - -@@ -439,9 +431,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) - snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); - snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); - -- err = ir_input_init(input_dev, &ir->ir, ir_type); -- if (err < 0) -- goto err_out_free; -+ ir->ir_type = ir_type; - - input_dev->name = ir->name; - input_dev->phys = ir->phys; -@@ -516,8 +506,6 @@ void cx88_ir_irq(struct cx88_core *core) - } - if (!ir->scount) { - /* nothing to sample */ -- if (ir->ir.keypressed && time_after(jiffies, ir->release)) -- ir_input_nokey(ir->input, &ir->ir); - return; - } - -@@ -553,7 +541,7 @@ void cx88_ir_irq(struct cx88_core *core) - - if (ircode == 0) { /* key still pressed */ - ir_dprintk("pulse distance decoded repeat code\n"); -- ir->release = jiffies + msecs_to_jiffies(120); -+ ir_repeat(ir->input); - break; - } - -@@ -567,10 +555,8 @@ void cx88_ir_irq(struct cx88_core *core) - break; - } - -- ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f); -- -- ir_input_keydown(ir->input, &ir->ir, (ircode >> 16) & 0x7f); -- ir->release = jiffies + msecs_to_jiffies(120); -+ ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0xff); -+ ir_keydown(ir->input, (ircode >> 16) & 0xff, 0); - break; - case CX88_BOARD_HAUPPAUGE: - case CX88_BOARD_HAUPPAUGE_DVB_T1: -@@ -606,16 +592,16 @@ void cx88_ir_irq(struct cx88_core *core) - if ( dev != 0x1e && dev != 0x1f ) - /* not a hauppauge remote */ - break; -- ir_input_keydown(ir->input, &ir->ir, code); -- ir->release = jiffies + msecs_to_jiffies(120); -+ ir_keydown(ir->input, code, toggle); - break; - case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); - ir_dprintk("biphase decoded: %x\n", ircode); - if ((ircode & 0xfffff000) != 0x3000) - break; -- ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f); -- ir->release = jiffies + msecs_to_jiffies(120); -+ /* Note: bit 0x800 being the toggle is assumed, not checked -+ with real hardware */ -+ ir_keydown(ir->input, ircode & 0x3f, ircode & 0x0800 ? 1 : 0); - break; - } - -diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h -index bdb03d3..33d161a 100644 ---- a/drivers/media/video/cx88/cx88.h -+++ b/drivers/media/video/cx88/cx88.h -@@ -636,6 +636,7 @@ extern struct videobuf_queue_ops cx8800_vbi_qops; - /* cx88-i2c.c */ - - extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); -+extern void cx88_i2c_init_ir(struct cx88_core *core); - - - /* ----------------------------------------------------------- */ -diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c -index 5c3fd94..6759cd5 100644 ---- a/drivers/media/video/em28xx/em28xx-input.c -+++ b/drivers/media/video/em28xx/em28xx-input.c -@@ -65,17 +65,14 @@ struct em28xx_ir_poll_result { - struct em28xx_IR { - struct em28xx *dev; - struct input_dev *input; -- struct ir_input_state ir; - char name[32]; - char phys[32]; - - /* poll external decoder */ - int polling; - struct delayed_work work; -- unsigned int last_toggle:1; - unsigned int full_code:1; - unsigned int last_readcount; -- unsigned int repeat_interval; - - int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); - -@@ -291,67 +288,39 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, - static void em28xx_ir_handle_key(struct em28xx_IR *ir) - { - int result; -- int do_sendkey = 0; - struct em28xx_ir_poll_result poll_result; - - /* read the registers containing the IR status */ - result = ir->get_key(ir, &poll_result); -- if (result < 0) { -+ if (unlikely(result < 0)) { - dprintk("ir->get_key() failed %d\n", result); - return; - } - -- dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x%02x\n", -- poll_result.toggle_bit, poll_result.read_count, -- ir->last_readcount, poll_result.rc_address, -- poll_result.rc_data[0]); -- -- if (ir->dev->chip_id == CHIP_ID_EM2874) { -- /* The em2874 clears the readcount field every time the -- register is read. The em2860/2880 datasheet says that it -- is supposed to clear the readcount, but it doesn't. So with -- the em2874, we are looking for a non-zero read count as -- opposed to a readcount that is incrementing */ -- ir->last_readcount = 0; -- } -- -- if (poll_result.read_count == 0) { -- /* The button has not been pressed since the last read */ -- } else if (ir->last_toggle != poll_result.toggle_bit) { -- /* A button has been pressed */ -- dprintk("button has been pressed\n"); -- ir->last_toggle = poll_result.toggle_bit; -- ir->repeat_interval = 0; -- do_sendkey = 1; -- } else if (poll_result.toggle_bit == ir->last_toggle && -- poll_result.read_count > 0 && -- poll_result.read_count != ir->last_readcount) { -- /* The button is still being held down */ -- dprintk("button being held down\n"); -- -- /* Debouncer for first keypress */ -- if (ir->repeat_interval++ > 9) { -- /* Start repeating after 1 second */ -- do_sendkey = 1; -- } -- } -- -- if (do_sendkey) { -- dprintk("sending keypress\n"); -- -+ if (unlikely(poll_result.read_count != ir->last_readcount)) { -+ dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__, -+ poll_result.toggle_bit, poll_result.read_count, -+ poll_result.rc_address, poll_result.rc_data[0]); - if (ir->full_code) -- ir_input_keydown(ir->input, &ir->ir, -- poll_result.rc_address << 8 | -- poll_result.rc_data[0]); -+ ir_keydown(ir->input, -+ poll_result.rc_address << 8 | -+ poll_result.rc_data[0], -+ poll_result.toggle_bit); - else -- ir_input_keydown(ir->input, &ir->ir, -- poll_result.rc_data[0]); -- -- ir_input_nokey(ir->input, &ir->ir); -+ ir_keydown(ir->input, -+ poll_result.rc_data[0], -+ poll_result.toggle_bit); -+ -+ if (ir->dev->chip_id == CHIP_ID_EM2874) -+ /* The em2874 clears the readcount field every time the -+ register is read. The em2860/2880 datasheet says that it -+ is supposed to clear the readcount, but it doesn't. So with -+ the em2874, we are looking for a non-zero read count as -+ opposed to a readcount that is incrementing */ -+ ir->last_readcount = 0; -+ else -+ ir->last_readcount = poll_result.read_count; - } -- -- ir->last_readcount = poll_result.read_count; -- return; - } - - static void em28xx_ir_work(struct work_struct *work) -@@ -466,11 +435,6 @@ int em28xx_ir_init(struct em28xx *dev) - usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); - strlcat(ir->phys, "/input0", sizeof(ir->phys)); - -- /* Set IR protocol */ -- err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER); -- if (err < 0) -- goto err_out_free; -- - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_USB; -diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c -index 20090e3..7b9ec6e 100644 ---- a/drivers/media/video/em28xx/em28xx-video.c -+++ b/drivers/media/video/em28xx/em28xx-video.c -@@ -654,12 +654,12 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) - } - - if (buf != NULL && dev->capture_type == 2) { -- if (len > 4 && p[0] == 0x88 && p[1] == 0x88 && -+ if (len >= 4 && p[0] == 0x88 && p[1] == 0x88 && - p[2] == 0x88 && p[3] == 0x88) { - p += 4; - len -= 4; - } -- if (len > 4 && p[0] == 0x22 && p[1] == 0x5a) { -+ if (len >= 4 && p[0] == 0x22 && p[1] == 0x5a) { - em28xx_isocdbg("Video frame %d, len=%i, %s\n", - p[2], len, (p[2] & 1) ? - "odd" : "even"); -diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h -index b252d1b..6216786 100644 ---- a/drivers/media/video/em28xx/em28xx.h -+++ b/drivers/media/video/em28xx/em28xx.h -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) - #include - #endif -diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c -index 830d47b..0cae5b8 100644 ---- a/drivers/media/video/hdpvr/hdpvr-core.c -+++ b/drivers/media/video/hdpvr/hdpvr-core.c -@@ -286,6 +286,8 @@ static int hdpvr_probe(struct usb_interface *interface, - goto error; - } - -+ dev->workqueue = 0; -+ - /* register v4l2_device early so it can be used for printks */ - if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { - err("v4l2_device_register failed"); -@@ -380,6 +382,9 @@ static int hdpvr_probe(struct usb_interface *interface, - - error: - if (dev) { -+ /* Destroy single thread */ -+ if (dev->workqueue) -+ destroy_workqueue(dev->workqueue); - /* this frees allocated memory */ - hdpvr_delete(dev); - } -diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c -index 29d4397..27ae8bb 100644 ---- a/drivers/media/video/ir-kbd-i2c.c -+++ b/drivers/media/video/ir-kbd-i2c.c -@@ -47,7 +47,7 @@ - #include - #include - --#include -+#include - #include - - /* ----------------------------------------------------------------------- */ -@@ -272,11 +272,8 @@ static void ir_key_poll(struct IR_i2c *ir) - return; - } - -- if (0 == rc) { -- ir_input_nokey(ir->input, &ir->ir); -- } else { -- ir_input_keydown(ir->input, &ir->ir, ir_key); -- } -+ if (rc) -+ ir_keydown(ir->input, ir_key, 0); - } - - static void ir_work(struct work_struct *work) -@@ -439,10 +436,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) - dev_name(&client->dev)); - - /* init + register input device */ -- err = ir_input_init(input_dev, &ir->ir, ir_type); -- if (err < 0) -- goto err_out_free; -- -+ ir->ir_type = ir_type; - input_dev->id.bustype = BUS_I2C; - input_dev->name = ir->name; - input_dev->phys = ir->phys; -diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c -index b482478..bba6115 100644 ---- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c -+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c -@@ -223,7 +223,10 @@ int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp) - " pvr2_ioread_setup (setup) id=%p",cp); - pvr2_stream_kill(sp); - ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT); -- if (ret < 0) return ret; -+ if (ret < 0) { -+ mutex_unlock(&cp->mutex); -+ return ret; -+ } - for (idx = 0; idx < BUFFER_COUNT; idx++) { - bp = pvr2_stream_get_buffer(sp,idx); - pvr2_buffer_set_buffer(bp, -diff --git a/include/linux/input.h b/include/linux/input.h -index 6fcc910..fe2633c 100644 ---- a/include/linux/input.h -+++ b/include/linux/input.h -@@ -34,7 +34,7 @@ struct input_event { - * Protocol version. - */ - --#define EV_VERSION 0x010000 -+#define EV_VERSION 0x010001 - - /* - * IOCTLs (0x00 - 0x7f) -@@ -56,12 +56,22 @@ struct input_absinfo { - __s32 resolution; - }; - -+struct keycode_table_entry { -+ __u32 keycode; /* e.g. KEY_A */ -+ __u32 index; /* Index for the given scan/key table, on EVIOCGKEYCODEBIG */ -+ __u32 len; /* Length of the scancode */ -+ __u32 reserved[2]; /* Reserved for future usage */ -+ char *scancode; /* scancode, in machine-endian */ -+}; -+ - #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ - #define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ - #define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */ - #define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */ - #define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */ - #define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */ -+#define EVIOCGKEYCODEBIG _IOR('E', 0x04, struct keycode_table_entry) /* get keycode */ -+#define EVIOCSKEYCODEBIG _IOW('E', 0x04, struct keycode_table_entry) /* set keycode */ - - #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ - #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */ -@@ -1066,13 +1076,22 @@ struct ff_effect { - * @keycodemax: size of keycode table - * @keycodesize: size of elements in keycode table - * @keycode: map of scancodes to keycodes for this device -- * @setkeycode: optional method to alter current keymap, used to implement -+ * @setkeycode: optional legacy method to alter current keymap, used to -+ * implement sparse keymaps. Shouldn't be used on new drivers -+ * @getkeycode: optional legacy method to retrieve current keymap. -+ * Shouldn't be used on new drivers. -+ * @setkeycodebig: optional method to alter current keymap, used to implement - * sparse keymaps. If not supplied default mechanism will be used. - * The method is being called while holding event_lock and thus must - * not sleep -- * @getkeycode: optional method to retrieve current keymap. If not supplied -- * default mechanism will be used. The method is being called while -- * holding event_lock and thus must not sleep -+ * @getkeycodebig_from_index: optional method to retrieve current keymap from -+ * an array index. If not supplied default mechanism will be used. -+ * The method is being called while holding event_lock and thus must -+ * not sleep -+ * @getkeycodebig_from_scancode: optional method to retrieve current keymap -+ * from an scancode. If not supplied default mechanism will be used. -+ * The method is being called while holding event_lock and thus must -+ * not sleep - * @ff: force feedback structure associated with the device if device - * supports force feedback effects - * @repeat_key: stores key code of the last key pressed; used to implement -@@ -1147,6 +1166,12 @@ struct input_dev { - unsigned int scancode, unsigned int keycode); - int (*getkeycode)(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode); -+ int (*setkeycodebig)(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry); -+ int (*getkeycodebig_from_index)(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry); -+ int (*getkeycodebig_from_scancode)(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry); - - struct ff_device *ff; - -@@ -1422,6 +1447,10 @@ int input_get_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode); - int input_set_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int keycode); -+int input_get_keycode_big(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry); -+int input_set_keycode_big(struct input_dev *dev, -+ struct keycode_table_entry *kt_entry); - - extern struct class input_class; - -diff --git a/include/media/ir-core.h b/include/media/ir-core.h -index ad1303f..513e60d 100644 ---- a/include/media/ir-core.h -+++ b/include/media/ir-core.h -@@ -47,15 +47,21 @@ enum rc_driver_type { - * is opened. - * @close: callback to allow drivers to disable polling/irq when IR input device - * is opened. -+ * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs) -+ * @s_tx_carrier: set transmit carrier frequency -+ * @tx_ir: transmit IR - */ - struct ir_dev_props { - enum rc_driver_type driver_type; - unsigned long allowed_protos; - u32 scanmask; -- void *priv; -+ void *priv; - int (*change_protocol)(void *priv, u64 ir_type); - int (*open)(void *priv); - void (*close)(void *priv); -+ int (*s_tx_mask)(void *priv, u32 mask); -+ int (*s_tx_carrier)(void *priv, u32 carrier); -+ int (*tx_ir)(void *priv, int *txbuf, u32 n); - }; - - struct ir_input_dev { -diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h -index 0506e45..5e96d7a 100644 ---- a/include/media/ir-kbd-i2c.h -+++ b/include/media/ir-kbd-i2c.h -@@ -11,7 +11,7 @@ struct IR_i2c { - struct i2c_client *c; - struct input_dev *input; - struct ir_input_state ir; -- -+ u64 ir_type; - /* Used to avoid fast repeating */ - unsigned char old; - -diff --git a/include/media/lirc.h b/include/media/lirc.h -new file mode 100644 -index 0000000..42c467c ---- /dev/null -+++ b/include/media/lirc.h -@@ -0,0 +1,165 @@ -+/* -+ * lirc.h - linux infrared remote control header file -+ * last modified 2010/07/13 by Jarod Wilson -+ */ -+ -+#ifndef _LINUX_LIRC_H -+#define _LINUX_LIRC_H -+ -+#include -+#include -+ -+#define PULSE_BIT 0x01000000 -+#define PULSE_MASK 0x00FFFFFF -+ -+#define LIRC_MODE2_SPACE 0x00000000 -+#define LIRC_MODE2_PULSE 0x01000000 -+#define LIRC_MODE2_FREQUENCY 0x02000000 -+#define LIRC_MODE2_TIMEOUT 0x03000000 -+ -+#define LIRC_VALUE_MASK 0x00FFFFFF -+#define LIRC_MODE2_MASK 0xFF000000 -+ -+#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE) -+#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE) -+#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY) -+#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT) -+ -+#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK) -+#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK) -+ -+#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE) -+#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE) -+#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY) -+#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT) -+ -+/* used heavily by lirc userspace */ -+#define lirc_t int -+ -+/*** lirc compatible hardware features ***/ -+ -+#define LIRC_MODE2SEND(x) (x) -+#define LIRC_SEND2MODE(x) (x) -+#define LIRC_MODE2REC(x) ((x) << 16) -+#define LIRC_REC2MODE(x) ((x) >> 16) -+ -+#define LIRC_MODE_RAW 0x00000001 -+#define LIRC_MODE_PULSE 0x00000002 -+#define LIRC_MODE_MODE2 0x00000004 -+#define LIRC_MODE_LIRCCODE 0x00000010 -+ -+ -+#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) -+#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) -+#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) -+#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) -+ -+#define LIRC_CAN_SEND_MASK 0x0000003f -+ -+#define LIRC_CAN_SET_SEND_CARRIER 0x00000100 -+#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 -+#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 -+ -+#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) -+#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) -+#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) -+#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) -+ -+#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) -+ -+#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16) -+#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16) -+ -+#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000 -+#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 -+#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 -+#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 -+#define LIRC_CAN_SET_REC_FILTER 0x08000000 -+ -+#define LIRC_CAN_MEASURE_CARRIER 0x02000000 -+ -+#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) -+#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) -+ -+#define LIRC_CAN_NOTIFY_DECODE 0x01000000 -+ -+/*** IOCTL commands for lirc driver ***/ -+ -+#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32) -+ -+#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32) -+#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32) -+#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32) -+#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32) -+#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32) -+#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, __u32) -+#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32) -+ -+#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32) -+#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32) -+ -+#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, __u32) -+#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, __u32) -+#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, __u32) -+#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, __u32) -+ -+/* code length in bits, currently only for LIRC_MODE_LIRCCODE */ -+#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32) -+ -+#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32) -+#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32) -+/* Note: these can reset the according pulse_width */ -+#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32) -+#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32) -+#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32) -+#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, __u32) -+#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32) -+ -+/* -+ * when a timeout != 0 is set the driver will send a -+ * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is -+ * never sent, timeout is disabled by default -+ */ -+#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32) -+ -+/* 1 enables, 0 disables timeout reports in MODE2 */ -+#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32) -+ -+/* -+ * pulses shorter than this are filtered out by hardware (software -+ * emulation in lirc_dev?) -+ */ -+#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, __u32) -+/* -+ * spaces shorter than this are filtered out by hardware (software -+ * emulation in lirc_dev?) -+ */ -+#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32) -+/* -+ * if filter cannot be set independantly for pulse/space, this should -+ * be used -+ */ -+#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32) -+ -+/* -+ * if enabled from the next key press on the driver will send -+ * LIRC_MODE2_FREQUENCY packets -+ */ -+#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) -+ -+/* -+ * to set a range use -+ * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the -+ * lower bound first and later -+ * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound -+ */ -+ -+#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, __u32) -+#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32) -+ -+#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) -+ -+#define LIRC_SETUP_START _IO('i', 0x00000021) -+#define LIRC_SETUP_END _IO('i', 0x00000022) -+ -+#endif -diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h -new file mode 100644 -index 0000000..b1f6066 ---- /dev/null -+++ b/include/media/lirc_dev.h -@@ -0,0 +1,225 @@ -+/* -+ * LIRC base driver -+ * -+ * by Artur Lipowski -+ * This code is licensed under GNU GPL -+ * -+ */ -+ -+#ifndef _LINUX_LIRC_DEV_H -+#define _LINUX_LIRC_DEV_H -+ -+#define MAX_IRCTL_DEVICES 4 -+#define BUFLEN 16 -+ -+#define mod(n, div) ((n) % (div)) -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct lirc_buffer { -+ wait_queue_head_t wait_poll; -+ spinlock_t fifo_lock; -+ unsigned int chunk_size; -+ unsigned int size; /* in chunks */ -+ /* Using chunks instead of bytes pretends to simplify boundary checking -+ * And should allow for some performance fine tunning later */ -+ struct kfifo fifo; -+ u8 fifo_initialized; -+}; -+ -+static inline void lirc_buffer_clear(struct lirc_buffer *buf) -+{ -+ unsigned long flags; -+ -+ if (buf->fifo_initialized) { -+ spin_lock_irqsave(&buf->fifo_lock, flags); -+ kfifo_reset(&buf->fifo); -+ spin_unlock_irqrestore(&buf->fifo_lock, flags); -+ } else -+ WARN(1, "calling %s on an uninitialized lirc_buffer\n", -+ __func__); -+} -+ -+static inline int lirc_buffer_init(struct lirc_buffer *buf, -+ unsigned int chunk_size, -+ unsigned int size) -+{ -+ int ret; -+ -+ init_waitqueue_head(&buf->wait_poll); -+ spin_lock_init(&buf->fifo_lock); -+ buf->chunk_size = chunk_size; -+ buf->size = size; -+ ret = kfifo_alloc(&buf->fifo, size * chunk_size, GFP_KERNEL); -+ if (ret == 0) -+ buf->fifo_initialized = 1; -+ -+ return ret; -+} -+ -+static inline void lirc_buffer_free(struct lirc_buffer *buf) -+{ -+ if (buf->fifo_initialized) { -+ kfifo_free(&buf->fifo); -+ buf->fifo_initialized = 0; -+ } else -+ WARN(1, "calling %s on an uninitialized lirc_buffer\n", -+ __func__); -+} -+ -+static inline int lirc_buffer_len(struct lirc_buffer *buf) -+{ -+ int len; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&buf->fifo_lock, flags); -+ len = kfifo_len(&buf->fifo); -+ spin_unlock_irqrestore(&buf->fifo_lock, flags); -+ -+ return len; -+} -+ -+static inline int lirc_buffer_full(struct lirc_buffer *buf) -+{ -+ return lirc_buffer_len(buf) == buf->size * buf->chunk_size; -+} -+ -+static inline int lirc_buffer_empty(struct lirc_buffer *buf) -+{ -+ return !lirc_buffer_len(buf); -+} -+ -+static inline int lirc_buffer_available(struct lirc_buffer *buf) -+{ -+ return buf->size - (lirc_buffer_len(buf) / buf->chunk_size); -+} -+ -+static inline unsigned int lirc_buffer_read(struct lirc_buffer *buf, -+ unsigned char *dest) -+{ -+ unsigned int ret = 0; -+ -+ if (lirc_buffer_len(buf) >= buf->chunk_size) -+ ret = kfifo_out_locked(&buf->fifo, dest, buf->chunk_size, -+ &buf->fifo_lock); -+ return ret; -+ -+} -+ -+static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf, -+ unsigned char *orig) -+{ -+ unsigned int ret; -+ -+ ret = kfifo_in_locked(&buf->fifo, orig, buf->chunk_size, -+ &buf->fifo_lock); -+ -+ return ret; -+} -+ -+struct lirc_driver { -+ char name[40]; -+ int minor; -+ unsigned long code_length; -+ unsigned int buffer_size; /* in chunks holding one code each */ -+ int sample_rate; -+ unsigned long features; -+ -+ unsigned int chunk_size; -+ -+ void *data; -+ int min_timeout; -+ int max_timeout; -+ int (*add_to_buf) (void *data, struct lirc_buffer *buf); -+ struct lirc_buffer *rbuf; -+ int (*set_use_inc) (void *data); -+ void (*set_use_dec) (void *data); -+ struct file_operations *fops; -+ struct device *dev; -+ struct module *owner; -+}; -+ -+/* name: -+ * this string will be used for logs -+ * -+ * minor: -+ * indicates minor device (/dev/lirc) number for registered driver -+ * if caller fills it with negative value, then the first free minor -+ * number will be used (if available) -+ * -+ * code_length: -+ * length of the remote control key code expressed in bits -+ * -+ * sample_rate: -+ * -+ * data: -+ * it may point to any driver data and this pointer will be passed to -+ * all callback functions -+ * -+ * add_to_buf: -+ * add_to_buf will be called after specified period of the time or -+ * triggered by the external event, this behavior depends on value of -+ * the sample_rate this function will be called in user context. This -+ * routine should return 0 if data was added to the buffer and -+ * -ENODATA if none was available. This should add some number of bits -+ * evenly divisible by code_length to the buffer -+ * -+ * rbuf: -+ * if not NULL, it will be used as a read buffer, you will have to -+ * write to the buffer by other means, like irq's (see also -+ * lirc_serial.c). -+ * -+ * set_use_inc: -+ * set_use_inc will be called after device is opened -+ * -+ * set_use_dec: -+ * set_use_dec will be called after device is closed -+ * -+ * fops: -+ * file_operations for drivers which don't fit the current driver model. -+ * -+ * Some ioctl's can be directly handled by lirc_dev if the driver's -+ * ioctl function is NULL or if it returns -ENOIOCTLCMD (see also -+ * lirc_serial.c). -+ * -+ * owner: -+ * the module owning this struct -+ * -+ */ -+ -+ -+/* following functions can be called ONLY from user context -+ * -+ * returns negative value on error or minor number -+ * of the registered device if success -+ * contents of the structure pointed by p is copied -+ */ -+extern int lirc_register_driver(struct lirc_driver *d); -+ -+/* returns negative value on error or 0 if success -+*/ -+extern int lirc_unregister_driver(int minor); -+ -+/* Returns the private data stored in the lirc_driver -+ * associated with the given device file pointer. -+ */ -+void *lirc_get_pdata(struct file *file); -+ -+/* default file operations -+ * used by drivers if they override only some operations -+ */ -+int lirc_dev_fop_open(struct inode *inode, struct file *file); -+int lirc_dev_fop_close(struct inode *inode, struct file *file); -+unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait); -+long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -+ssize_t lirc_dev_fop_read(struct file *file, char *buffer, size_t length, -+ loff_t *ppos); -+ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, size_t length, -+ loff_t *ppos); -+ -+#endif -diff --git a/include/media/rc-map.h b/include/media/rc-map.h -index c78e99a..a329858 100644 ---- a/include/media/rc-map.h -+++ b/include/media/rc-map.h -@@ -17,8 +17,13 @@ - #define IR_TYPE_RC6 (1 << 2) /* Philips RC6 protocol */ - #define IR_TYPE_JVC (1 << 3) /* JVC protocol */ - #define IR_TYPE_SONY (1 << 4) /* Sony12/15/20 protocol */ -+#define IR_TYPE_LIRC (1 << 30) /* Pass raw IR to lirc userspace */ - #define IR_TYPE_OTHER (1u << 31) - -+#define IR_TYPE_ALL (IR_TYPE_RC5 | IR_TYPE_NEC | IR_TYPE_RC6 | \ -+ IR_TYPE_JVC | IR_TYPE_SONY | IR_TYPE_LIRC | \ -+ IR_TYPE_OTHER) -+ - struct ir_scancode { - u32 scancode; - u32 keycode; -@@ -87,6 +92,7 @@ void rc_map_init(void); - #define RC_MAP_KAIOMY "rc-kaiomy" - #define RC_MAP_KWORLD_315U "rc-kworld-315u" - #define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog" -+#define RC_MAP_LIRC "rc-lirc" - #define RC_MAP_MANLI "rc-manli" - #define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus" - #define RC_MAP_MSI_TVANYWHERE "rc-msi-tvanywhere" -@@ -107,6 +113,7 @@ void rc_map_init(void); - #define RC_MAP_PV951 "rc-pv951" - #define RC_MAP_RC5_HAUPPAUGE_NEW "rc-rc5-hauppauge-new" - #define RC_MAP_RC5_TV "rc-rc5-tv" -+#define RC_MAP_RC6_MCE "rc-rc6-mce" - #define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys" - #define RC_MAP_TBS_NEC "rc-tbs-nec" - #define RC_MAP_TERRATEC_CINERGY_XS "rc-terratec-cinergy-xs" diff --git a/linux-2.6-v4l-dvb-update.patch b/linux-2.6-v4l-dvb-update.patch index e69de29bb..0984884e9 100644 --- a/linux-2.6-v4l-dvb-update.patch +++ b/linux-2.6-v4l-dvb-update.patch @@ -0,0 +1,7725 @@ +v4l/dvb/rc media_tree updates from 2.6.39 + +commit f9d088784131609419595b51beb701d0f3aa6afc +Author: Jarod Wilson +Date: Tue Mar 22 17:23:15 2011 -0300 + + [media] rc: interim support for 32-bit NEC-ish scancodes + + The Apple and TiVo remotes I've got use an NEC-ish protocol, but rather + than a command/not_command pair, they have what appear to be vendor ID + bytes. This change makes the NEC decoder warn if the command/not_command + checksum fails, but then passes along a full 32-bit scancode for keymap + lookup. This change should make no difference for existing keymaps, + since they simply won't have 32-bit scancodes, but allows for a 32-bit + keymap. At the moment, that'll have to be uploaded by the user, but I've + got Apple and TiVo remote keymaps forthcoming. + + In the long run (2.6.40, hopefully), we should probably just always use + all 32 bits for all NEC keymaps, but this should get us by for 2.6.39. + + (Note that a few of the TiVo keys actuallly *do* pass the command + checksum, so for now, the keymap for this remote will have to be a mix + of 24-bit and 32-bit scancodes, but so be it). + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 4568844fff1dc46b8adb7364ac3a844aa34d1e38 +Author: Jarod Wilson +Date: Fri Mar 4 20:20:47 2011 -0300 + + [media] mceusb: topseed 0x0011 needs gen3 init for tx to work + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 514c3ef0671bdbdb1ae3708c63cce12e6f4b55f0 +Author: Jarod Wilson +Date: Fri Mar 4 19:53:05 2011 -0300 + + [media] lirc_zilog: error out if buffer read bytes != chunk size + + Give it a few tries, then exit. Prevents a possible endless loop + situation. + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 7f72453889801675b825083d7ebddc341ccbb331 +Author: Jarod Wilson +Date: Fri Mar 4 17:57:24 2011 -0300 + + [media] lirc: silence some compile warnings + + Both lirc_imon and lirc_sasem were causing gcc to complain about the + possible use of uninitialized variables. + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 37bda6318295a3412e191f1a5cb5a5bea2db59a5 +Author: Jarod Wilson +Date: Fri Mar 4 17:31:11 2011 -0300 + + [media] hdpvr: use same polling interval as other OS + + The hdpvr's IR part, in short, sucks. As observed with a usb traffic + sniffer, the Windows software for it uses a polling interval of 405ms. + Its still not behaving as well as I'd like even with this change, but + this inches us closer and closer to that point... + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 6ba973db97845b0b7322d1a0cd5348d3024d7387 +Author: Jarod Wilson +Date: Fri Mar 4 17:30:17 2011 -0300 + + [media] ir-kbd-i2c: pass device code w/key in hauppauge case + + The new hauppauge key tables use both device code button code. + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 246286a63b4820c1c039a836025c52ec79d18a2f +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 22:23:08 2011 -0300 + + [media] rc/keymaps: Remove the obsolete rc-rc5-tv keymap + + This keymap were used for the Hauppauge Black remote controller + only. It also contains some keycodes not found there. As the + Hauppauge Black is now part of the hauppauge keymap, just remove + it. + + Also, remove the modprobe hacks to select between the Gray + and the Black versions of the remote controller as: + - Both are supported by default by the keymap; + - If the user just wants one keyboard supported, + it is just a matter of changing the keymap via + the userspace tool (ir-keytable), removing + the keys that he doesn't desire. As ir-keytable + auto-loads the keys via udev, this is better than + obscure modprobe parameters. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit af2a42cc5eec9659bac301885ac795be81d019c8 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:48 2011 -0300 + + [media] remove the old RC_MAP_HAUPPAUGE_NEW RC map + + The rc-hauppauge-new map is a messy thing, as it bundles 3 + + different remote controllers as if they were just one, + discarding the address byte. Also, some key maps are wrong. + + With the conversion to the new rc-core, it is likely that + most of the devices won't be working properly, as the i2c + driver and the raw decoders are now providing 16 bits for + the remote, instead of just 8. + + delete mode 100644 drivers/media/rc/keymaps/rc-hauppauge-new.c + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 1ef571252ec29a8b3674deb746bfaa8ad1b034c3 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:47 2011 -0300 + + [media] rc/keymaps: Rename Hauppauge table as rc-hauppauge + + There are two "hauppauge-new" keymaps, one with protocol + unknown, and the other with the protocol marked accordingly. + However, both tables are miss-named. + + Also, the old rc-hauppauge-new is broken, as it mixes + three different controllers as if they were just one. + + This patch solves half of the problem by renaming the + correct keycode table as just rc-hauppauge. This table + contains the codes for the four different types of + remote controllers found on Hauppauge cards, properly + mapped with their different addresses. + + create mode 100644 drivers/media/rc/keymaps/rc-hauppauge.c + delete mode 100644 drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c + [Jarod: fix up RC_MAP_HAUPPAUGE defines] + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 41abb2ee0ac34ecd8769b2ddd84caf67414ca0f7 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:45 2011 -0300 + + [media] rc-rc5-hauppauge-new: Fix Hauppauge Grey mapping + + The keys for the old black were messed with the ones for the + hauppauge grey. Fix it. + + Also, fixes some keycodes and order the keys according with + the way they appear inside the remote controller. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 80daad9d9ece3bbfd0f7cc13dbefc92e3ebb1f6f +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:44 2011 -0300 + + [media] rc-rc5-hauppauge-new: Add support for the old Black RC + + Hans borrowed me an old Black Hauppauge RC. Thanks to that, we + can fix the RC5 table for Hauppauge. + + Thanks-to: Hans Verkuil + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 9ba542ee399a091a56711d5bc1f778f39768a26d +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:43 2011 -0300 + + [media] rc-rc5-hauppauge-new: Add the old control to the table + + Adds the old grey remote controller to Hauppauge table. + + Hans borrowed me an old gray Hauppauge RC. Thanks to that, we + can fix the RC5 table for Hauppauge. + + Thanks-to: Hans Verkuil + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 8d198df40f2d6fe2bfb3b8818dce974b40a614e9 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:43 2011 -0300 + + [media] rc-winfast: Fix the keycode tables + + One of the remotes has a picture available at: + http://lirc.sourceforge.net/remotes/leadtek/Y04G0004.jpg + + As there's one variant with a set direction keys plus vol/chann + keys, and the same table is used for both models, change it to + represent all keys, avoiding the usage of weird function keys. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 434e6519a292096ee29303d74688ced038606842 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:42 2011 -0300 + + [media] a800: Fix a few wrong IR key assignments + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 674ff915ca5d7b40d710eb910afcf7f490b76ab0 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:41 2011 -0300 + + [media] opera1: Use multimedia keys instead of an app-specific mapping + + This driver uses an app-specific keymap for one of the tables. This + is wrong. Instead, use the standard keycodes. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit d59b1eedf5d5108cc90b9cfaf17f7845bad4f806 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:40 2011 -0300 + + [media] dw2102: Use multimedia keys instead of an app-specific mapping + + This driver uses an app-specific keymap for one of the tables. This + is wrong. Instead, use the standard keycodes. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 651cef86ff15697ad8a5659ecc9bc43f16ca07ba +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:39 2011 -0300 + + [media] rc/keymaps: Use KEY_LEFTMETA were pertinent + + Using xev and testing the "Windows" key on a normal keyboard, it + is mapped as KEY_LEFTMETA. So, as this is the standard code for + it, use it, instead of a generic, meaningless KEY_PROG1. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit bb8aeecec52791eacc727d8400ced9e1b230ec49 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:38 2011 -0300 + + [media] rc/keymaps: Fix most KEY_PROG[n] keycodes + + Those KEY_PROG[n] keys were used on places where the developer + didn't know for sure what key should be used. On several cases, + using KEY_RED, KEY_GREEN, KEY_YELLOW would be enough. On others, + there are specific keys for that already. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit 84c122769cca37480fbcd7de5a102f6221874247 +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:37 2011 -0300 + + [media] rc/keymaps: Use KEY_VIDEO for Video Source + + Each keyboard map were using a different definition for + the Source/Video Source key. + Behold Columbus were the only one using KEY_PROPS. + + As we want to standardize those keys at X11 and at + userspace applications, we need to use just one code + for it. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit ea35a76538a45e78cee889d2c462df71a9b34e4c +Author: Mauro Carvalho Chehab +Date: Mon Jan 24 12:18:36 2011 -0300 + + [media] rc/keymaps: use KEY_CAMERA for snapshots + + On a few places, KEY_MHP were used for snapshots. However, KEY_CAMERA + is used for it on all the other keyboards that have a snapshot/Picture + button. + + Signed-off-by: Mauro Carvalho Chehab + Signed-off-by: Jarod Wilson + +commit d33d27b1745fc72b042b6431dd29ee484fdabbcc +Author: Andy Walls +Date: Thu Feb 17 21:32:06 2011 -0300 + + [media] lirc_zilog: Update TODO list based on work completed and revised plans + + Update the TODO.lirc_zilog based on what has been completed. Also revised + the development plan for lirc_zilog to not try and split Tx/Rx for one IR + transceiver unit between lirc_zilog and ir-kbd-i2c, since that would be a + ref-counting nightmare. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 1a9cb97924e71b33a5d1a59facd58e1a584daa97 +Author: Andy Walls +Date: Thu Feb 17 21:14:13 2011 -0300 + + [media] lirc_zilog: Fix somewhat confusing information messages in ir_probe() + + The total sequence of messages emitted by the ir_porbe() calls + for a transceiver's two i2c_clients was confusing. Clean it up a bit. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit cf141c455938cb245b6bf489c832d0c2e3833686 +Author: Andy Walls +Date: Thu Feb 17 20:50:38 2011 -0300 + + [media] lirc_zilog: Add locking of the i2c_clients when in use + + Lock the i2c_client pointers and prevent i2c_client removal when + lirc_zilog is perfoming a series of operations that require valid + i2c_client pointers. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 6f4276ac6e98a05833aa7e49e438fec198e537e8 +Author: Andy Walls +Date: Mon Feb 7 22:30:55 2011 -0300 + + [media] lirc_zilog: Add ref counting of struct IR, IR_tx, and IR_rx + + This is a major change to add pointer reference counting for + struct IR, struct IR_tx, and struct IR_rx object instances. + This ref counting gets lirc_zilog closer to gracefully handling + bridge drivers and hot-unplugged USB devices disappearing out from + under lirc_zilog when the /dev/lircN node is still open. (mutexes + to protect the i2c_client pointers in struct IR_tx and struct IR_rx + still need to be added.) + + This reference counting also helps lirc_zilog clean up properly + when the i2c_clients disappear. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit f3bc78dbb5942f1827a97329b1c095903329aa8b +Author: Andy Walls +Date: Thu Jan 27 23:02:20 2011 -0300 + + [media] lirc_zilog: Move constants from ir_probe() into the lirc_driver template + + ir_probe() makes a number of constant assignments into the lirc_driver + object after copying in a template. Make better use of the template. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 6f61cb53e2b8f6c65cf2c6b3e3710233c643e6ce +Author: Andy Walls +Date: Thu Jan 27 22:32:44 2011 -0300 + + [media] lirc_zilog: Always allocate a Rx lirc_buffer object + + Always allocate a lirc_buffer object, instead of just upon setup of + the Rx i2c_client. If we do not allocate a lirc_buffer object, because + we are not handling the Rx i2c_client, lirc_dev will allocate its own + lirc_buffer anyway and not tell us about its location. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 8941d66476b33d339408f66898766e0d8ac2cb0a +Author: Andy Walls +Date: Thu Jan 27 02:34:13 2011 -0300 + + [media] lirc_zilog: Remove unneeded rx->buf_lock + + Remove the rx->buf_lock that protected the rx->buf lirc_buffer. The + underlying operations on the objects within the lirc_buffer are already + protected by spinlocks, or the objects are constant (e.g. chunk_size). + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit fa2d70732b5699cd3bc9fc0e82c154e1410857e4 +Author: Andy Walls +Date: Thu Jan 27 02:10:42 2011 -0300 + + [media] lirc_zilog: Don't acquire the rx->buf_lock in the poll() function + + There is no need to take the rx->buf_lock in the the poll() function + as all the underling calls made on objects in the rx->buf lirc_buffer object + are protected by spinlocks. + + Corrected a bad error return value in poll(): return POLLERR instead + of -ENODEV. + + Added some comments to poll() for when, in the future, I forget what + poll() and poll_wait() are supposed to do. + + [Jarod: minor debug spew fix] + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 45a0dd2e9575f72693c94920e8d189ea395d5b5d +Author: Andy Walls +Date: Thu Jan 27 00:04:15 2011 -0300 + + [media] lirc_zilog: Use kernel standard methods for marking device non-seekable + + lirc_zilog had its own llseek stub that returned -ESPIPE. Get rid of + it and use the kernel's no_llseek() and nonseekable_open() functions + instead. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit c4c4362e1e1bd1a39f186b96ba5b0df74470f101 +Author: Andy Walls +Date: Wed Jan 26 22:04:24 2011 -0300 + + [media] lirc_zilog: Convert the instance open count to an atomic_t + + The open count is simply used for deciding if the Rx polling thread + needs to poll the IR chip for userspace. Simplify the manipulation + of the open count by using an atomic_t and not requiring a lock + The polling thread errantly didn't try to take the lock anyway. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 7f94125db5889c202b95e717ccbe9e35de63c14a +Author: Andy Walls +Date: Wed Jan 26 21:48:32 2011 -0300 + + [media] lirc_zilog: Convert ir_device instance array to a linked list + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit d2a47dc2e351e6cf33b98f0d3339d6d39fd8ed8b +Author: Andy Walls +Date: Wed Jan 26 21:25:47 2011 -0300 + + [media] lirc_zilog: Remove broken, ineffective reference counting + + The set_use_inc() and set_use_dec() functions tried to lock + the underlying bridge driver device instance in memory by + changing the use count on the device's i2c_clients. This + worked for PCI devices (ivtv, cx18, bttv). It doesn't + work for hot-pluggable usb devices (pvrusb2 and hdpvr). + With usb device instances, the driver may get locked into + memory, but the unplugged hardware is gone. + + The set_use_inc() set_use_dec() functions also tried to have + lirc_zilog change its own module refernce count, which is + racy and not guaranteed to work. The lirc_dev module does + actually perform proper module ref count manipulation on the + lirc_zilog module, so there is need for lirc_zilog to + attempt a buggy module get on itself anyway. + + lirc_zilog also errantly called these functions on itself + in open() and close(), but lirc_dev did that already too. + + So let's just gut the bodies of the set_use_*() functions, + and remove the extra calls to them from within lirc_zilog. + + Proper reference counting of the struct IR, IR_rx, and IR_tx + objects -- to handle the case when the underlying + bttv, ivtv, cx18, hdpvr, or pvrusb2 bridge driver module or + device instance goes away -- will be added in subsequent + patches. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 767dd925f017bd0f0363f827509cebfaf0bb2b57 +Author: Andy Walls +Date: Wed Jan 26 21:06:43 2011 -0300 + + [media] lirc_zilog: Restore checks for existence of the IR_tx object + + This reverts commit 8090232a237ab62e22307fc060097da1a283dd66 and + adds an additional check for ir->tx == NULL. + + The user may need us to handle an RX only unit. Apparently + there are TV capture units in existence with Rx only wiring + and/or RX only firmware for the on-board Zilog Z8 IR unit. + + Signed-off-by: Andy Walls + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 91f27e09d7bba99341bd8ce035995ae21ff493f7 +Author: Jarod Wilson +Date: Wed Mar 2 13:23:52 2011 -0300 + + [media] hdpvr: i2c master enhancements + + Make the hdpvr's i2c master implementation more closely mirror that of + the pvrusb2 driver. Currently makes no significant difference in IR + reception behavior with ir-kbd-i2c (i.e., it still sucks). + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit c1ba04cf3a0626f725795e3a853654928596d522 +Author: Jarod Wilson +Date: Tue Feb 1 16:27:05 2011 -0300 + + [media] imon: add more panel scancode mappings + + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 9cd4f638d57b01c5d901f73c94b08fad4aa0b295 +Author: Jarod Wilson +Date: Mon Jan 24 18:22:12 2011 -0300 + + [media] docs: fix typo in lirc_device_interface.xml + + Reported-by: Daniel Burr + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 97ad124749a060d8c4f5461111911474db3b555f +Author: Mauro Carvalho Chehab +Date: Tue Mar 22 17:17:56 2011 -0300 + + ite-cir: Fix a breakage caused by my cleanup patch + + Signed-off-by: Mauro Carvalho Chehab + +commit a38fc7a384bd679f2550e2a2323ff3e690d4ffd7 +Author: Juan J. Garcia de Soria +Date: Wed Mar 16 17:14:53 2011 -0300 + + [media] lirc: remove staging lirc_it87 and lirc_ite8709 drivers + + Remove older drivers lirc_it87 and lirc_ite8709 from the LIRC staging area, + since they're now superceded by ite-cir. + + Signed-off-by: Juan J. Garcia de Soria + Tested-by: Stephan Raue + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit e1bede3475c792a5c4793ec3cc929efa24aaae64 +Author: Mauro Carvalho Chehab +Date: Tue Mar 22 15:12:40 2011 -0300 + + [media] ite-cir: Fix some CodingStyle issues + + Cc: Juan J. Garcia de Soria + Cc: Stephan Raue + Cc: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + +commit 9e8739744ccc917011a91e489339278d7bb14eac +Author: Juan J. Garcia de Soria +Date: Wed Mar 16 17:14:52 2011 -0300 + + [media] rc: New rc-based ite-cir driver for several ITE CIRs + + This is a second version of an rc-core based driver for the ITE Tech IT8712F + CIR and now for a pair of other variants of the IT8512 CIR too. + + This driver should replace the lirc_it87 and lirc_ite8709 currently living in + the LIRC staging directory. + + The driver should support the ITE8704, ITE8713, ITE8708 and ITE8709 (this last + one yet untested) PNP ID's. + + The code doesn'te reuse code from the pre-existing LIRC drivers, but has been + written from scratch using the nuvoton.cir driver as a skeleton. + + This new driver shouldn't exhibit timing problems when running under load (or + with interrupts disabled for relatively long times). It works OOTB with the + RC6 MCE remote bundled with the ASUS EEEBox. TX support is implemented, but + I'm unable to test it since my hardware lacks TX capability. + + Signed-off-by: Juan J. Garcia de Soria + Tested-by: Stephan Raue + Signed-off-by: Jarod Wilson + Signed-off-by: Mauro Carvalho Chehab + .../DocBook/v4l/lirc_device_interface.xml | 2 +- + drivers/media/dvb/dvb-usb/a800.c | 8 +- + drivers/media/dvb/dvb-usb/digitv.c | 2 +- + drivers/media/dvb/dvb-usb/dw2102.c | 40 +- + drivers/media/dvb/dvb-usb/opera1.c | 33 +- + drivers/media/dvb/siano/sms-cards.c | 2 +- + drivers/media/dvb/ttpci/budget-ci.c | 15 +- + drivers/media/rc/Kconfig | 13 + + drivers/media/rc/Makefile | 1 + + drivers/media/rc/imon.c | 11 +- + drivers/media/rc/ir-nec-decoder.c | 10 +- + drivers/media/rc/ite-cir.c | 1736 ++++++++++++++++++++ + drivers/media/rc/ite-cir.h | 481 ++++++ + drivers/media/rc/keymaps/Makefile | 4 +- + drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c | 6 +- + drivers/media/rc/keymaps/rc-avermedia-dvbt.c | 4 +- + drivers/media/rc/keymaps/rc-avermedia-m135a.c | 2 +- + .../media/rc/keymaps/rc-avermedia-m733a-rm-k6.c | 2 +- + drivers/media/rc/keymaps/rc-avermedia-rm-ks.c | 2 +- + drivers/media/rc/keymaps/rc-behold-columbus.c | 2 +- + drivers/media/rc/keymaps/rc-behold.c | 2 +- + drivers/media/rc/keymaps/rc-budget-ci-old.c | 3 +- + drivers/media/rc/keymaps/rc-cinergy.c | 2 +- + drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c | 2 +- + drivers/media/rc/keymaps/rc-encore-enltv.c | 4 +- + drivers/media/rc/keymaps/rc-encore-enltv2.c | 2 +- + drivers/media/rc/keymaps/rc-flydvb.c | 4 +- + drivers/media/rc/keymaps/rc-hauppauge-new.c | 100 -- + drivers/media/rc/keymaps/rc-hauppauge.c | 241 +++ + drivers/media/rc/keymaps/rc-imon-mce.c | 2 +- + drivers/media/rc/keymaps/rc-imon-pad.c | 2 +- + drivers/media/rc/keymaps/rc-kworld-315u.c | 2 +- + .../media/rc/keymaps/rc-kworld-plus-tv-analog.c | 2 +- + drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c | 2 +- + drivers/media/rc/keymaps/rc-nebula.c | 2 +- + drivers/media/rc/keymaps/rc-norwood.c | 2 +- + drivers/media/rc/keymaps/rc-pctv-sedna.c | 2 +- + drivers/media/rc/keymaps/rc-pixelview-mk12.c | 2 +- + drivers/media/rc/keymaps/rc-pixelview-new.c | 2 +- + drivers/media/rc/keymaps/rc-pixelview.c | 2 +- + drivers/media/rc/keymaps/rc-pv951.c | 4 +- + drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c | 141 -- + drivers/media/rc/keymaps/rc-rc5-tv.c | 81 - + drivers/media/rc/keymaps/rc-rc6-mce.c | 2 +- + .../media/rc/keymaps/rc-real-audio-220-32-keys.c | 2 +- + drivers/media/rc/keymaps/rc-winfast.c | 22 +- + drivers/media/rc/mceusb.c | 4 +- + drivers/media/video/cx18/cx18-i2c.c | 2 +- + drivers/media/video/cx23885/cx23885-input.c | 2 +- + drivers/media/video/cx88/cx88-input.c | 4 +- + drivers/media/video/em28xx/em28xx-cards.c | 10 +- + drivers/media/video/hdpvr/hdpvr-i2c.c | 72 +- + drivers/media/video/ir-kbd-i2c.c | 18 +- + drivers/media/video/ivtv/ivtv-i2c.c | 5 +- + drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 4 +- + drivers/media/video/saa7134/saa7134-input.c | 2 +- + drivers/staging/lirc/Kconfig | 12 - + drivers/staging/lirc/Makefile | 2 - + drivers/staging/lirc/TODO.lirc_zilog | 51 +- + drivers/staging/lirc/lirc_imon.c | 2 +- + drivers/staging/lirc/lirc_it87.c | 1027 ------------ + drivers/staging/lirc/lirc_it87.h | 116 -- + drivers/staging/lirc/lirc_ite8709.c | 542 ------ + drivers/staging/lirc/lirc_sasem.c | 2 +- + drivers/staging/lirc/lirc_zilog.c | 814 ++++++---- + include/media/rc-map.h | 4 +- + include/media/soc_camera.h | 2 + + 67 files changed, 3128 insertions(+), 2513 deletions(-) + +--- +diff --git a/Documentation/DocBook/v4l/lirc_device_interface.xml b/Documentation/DocBook/v4l/lirc_device_interface.xml +index 68134c0..0e0453f 100644 +--- a/Documentation/DocBook/v4l/lirc_device_interface.xml ++++ b/Documentation/DocBook/v4l/lirc_device_interface.xml +@@ -45,7 +45,7 @@ describing an IR signal are read from the chardev. + The data written to the chardev is a pulse/space sequence of integer + values. Pulses and spaces are only marked implicitly by their position. The + data must start and end with a pulse, therefore, the data must always include +-an unevent number of samples. The write function must block until the data has ++an uneven number of samples. The write function must block until the data has + been transmitted by the hardware. + + +diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c +index 53b93a4..f8e9bf1 100644 +--- a/drivers/media/dvb/dvb-usb/a800.c ++++ b/drivers/media/dvb/dvb-usb/a800.c +@@ -38,8 +38,8 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr + } + + static struct rc_map_table rc_map_a800_table[] = { +- { 0x0201, KEY_PROG1 }, /* SOURCE */ +- { 0x0200, KEY_POWER }, /* POWER */ ++ { 0x0201, KEY_MODE }, /* SOURCE */ ++ { 0x0200, KEY_POWER2 }, /* POWER */ + { 0x0205, KEY_1 }, /* 1 */ + { 0x0206, KEY_2 }, /* 2 */ + { 0x0207, KEY_3 }, /* 3 */ +@@ -52,8 +52,8 @@ static struct rc_map_table rc_map_a800_table[] = { + { 0x0212, KEY_LEFT }, /* L / DISPLAY */ + { 0x0211, KEY_0 }, /* 0 */ + { 0x0213, KEY_RIGHT }, /* R / CH RTN */ +- { 0x0217, KEY_PROG2 }, /* SNAP SHOT */ +- { 0x0210, KEY_PROG3 }, /* 16-CH PREV */ ++ { 0x0217, KEY_CAMERA }, /* SNAP SHOT */ ++ { 0x0210, KEY_LAST }, /* 16-CH PREV */ + { 0x021e, KEY_VOLUMEDOWN }, /* VOL DOWN */ + { 0x020c, KEY_ZOOM }, /* FULL SCREEN */ + { 0x021f, KEY_VOLUMEUP }, /* VOL UP */ +diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c +index f2dbce7..f6344cd 100644 +--- a/drivers/media/dvb/dvb-usb/digitv.c ++++ b/drivers/media/dvb/dvb-usb/digitv.c +@@ -176,7 +176,7 @@ static struct rc_map_table rc_map_digitv_table[] = { + { 0xaf59, KEY_AUX }, + { 0x5f5a, KEY_DVD }, + { 0x6f5a, KEY_POWER }, +- { 0x9f5a, KEY_MHP }, /* labelled 'Picture' */ ++ { 0x9f5a, KEY_CAMERA }, /* labelled 'Picture' */ + { 0xaf5a, KEY_AUDIO }, + { 0x5f65, KEY_INFO }, + { 0x6f65, KEY_F13 }, /* 16:9 */ +diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c +index 98cf302..f5b9da1 100644 +--- a/drivers/media/dvb/dvb-usb/dw2102.c ++++ b/drivers/media/dvb/dvb-usb/dw2102.c +@@ -1224,8 +1224,8 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) + } + + static struct rc_map_table rc_map_dw210x_table[] = { +- { 0xf80a, KEY_Q }, /*power*/ +- { 0xf80c, KEY_M }, /*mute*/ ++ { 0xf80a, KEY_POWER2 }, /*power*/ ++ { 0xf80c, KEY_MUTE }, /*mute*/ + { 0xf811, KEY_1 }, + { 0xf812, KEY_2 }, + { 0xf813, KEY_3 }, +@@ -1236,25 +1236,25 @@ static struct rc_map_table rc_map_dw210x_table[] = { + { 0xf818, KEY_8 }, + { 0xf819, KEY_9 }, + { 0xf810, KEY_0 }, +- { 0xf81c, KEY_PAGEUP }, /*ch+*/ +- { 0xf80f, KEY_PAGEDOWN }, /*ch-*/ +- { 0xf81a, KEY_O }, /*vol+*/ +- { 0xf80e, KEY_Z }, /*vol-*/ +- { 0xf804, KEY_R }, /*rec*/ +- { 0xf809, KEY_D }, /*fav*/ +- { 0xf808, KEY_BACKSPACE }, /*rewind*/ +- { 0xf807, KEY_A }, /*fast*/ +- { 0xf80b, KEY_P }, /*pause*/ +- { 0xf802, KEY_ESC }, /*cancel*/ +- { 0xf803, KEY_G }, /*tab*/ ++ { 0xf81c, KEY_CHANNELUP }, /*ch+*/ ++ { 0xf80f, KEY_CHANNELDOWN }, /*ch-*/ ++ { 0xf81a, KEY_VOLUMEUP }, /*vol+*/ ++ { 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/ ++ { 0xf804, KEY_RECORD }, /*rec*/ ++ { 0xf809, KEY_FAVORITES }, /*fav*/ ++ { 0xf808, KEY_REWIND }, /*rewind*/ ++ { 0xf807, KEY_FASTFORWARD }, /*fast*/ ++ { 0xf80b, KEY_PAUSE }, /*pause*/ ++ { 0xf802, KEY_ESC }, /*cancel*/ ++ { 0xf803, KEY_TAB }, /*tab*/ + { 0xf800, KEY_UP }, /*up*/ +- { 0xf81f, KEY_ENTER }, /*ok*/ +- { 0xf801, KEY_DOWN }, /*down*/ +- { 0xf805, KEY_C }, /*cap*/ +- { 0xf806, KEY_S }, /*stop*/ +- { 0xf840, KEY_F }, /*full*/ +- { 0xf81e, KEY_W }, /*tvmode*/ +- { 0xf81b, KEY_B }, /*recall*/ ++ { 0xf81f, KEY_OK }, /*ok*/ ++ { 0xf801, KEY_DOWN }, /*down*/ ++ { 0xf805, KEY_CAMERA }, /*cap*/ ++ { 0xf806, KEY_STOP }, /*stop*/ ++ { 0xf840, KEY_ZOOM }, /*full*/ ++ { 0xf81e, KEY_TV }, /*tvmode*/ ++ { 0xf81b, KEY_LAST }, /*recall*/ + }; + + static struct rc_map_table rc_map_tevii_table[] = { +diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c +index 1f1b7d6..7e569f4 100644 +--- a/drivers/media/dvb/dvb-usb/opera1.c ++++ b/drivers/media/dvb/dvb-usb/opera1.c +@@ -342,23 +342,22 @@ static struct rc_map_table rc_map_opera1_table[] = { + {0x49b6, KEY_8}, + {0x05fa, KEY_9}, + {0x45ba, KEY_0}, +- {0x09f6, KEY_UP}, /*chanup */ +- {0x1be5, KEY_DOWN}, /*chandown */ +- {0x5da3, KEY_LEFT}, /*voldown */ +- {0x5fa1, KEY_RIGHT}, /*volup */ +- {0x07f8, KEY_SPACE}, /*tab */ +- {0x1fe1, KEY_ENTER}, /*play ok */ +- {0x1be4, KEY_Z}, /*zoom */ +- {0x59a6, KEY_M}, /*mute */ +- {0x5ba5, KEY_F}, /*tv/f */ +- {0x19e7, KEY_R}, /*rec */ +- {0x01fe, KEY_S}, /*Stop */ +- {0x03fd, KEY_P}, /*pause */ +- {0x03fc, KEY_W}, /*<- -> */ +- {0x07f9, KEY_C}, /*capture */ +- {0x47b9, KEY_Q}, /*exit */ +- {0x43bc, KEY_O}, /*power */ +- ++ {0x09f6, KEY_CHANNELUP}, /*chanup */ ++ {0x1be5, KEY_CHANNELDOWN}, /*chandown */ ++ {0x5da3, KEY_VOLUMEDOWN}, /*voldown */ ++ {0x5fa1, KEY_VOLUMEUP}, /*volup */ ++ {0x07f8, KEY_SPACE}, /*tab */ ++ {0x1fe1, KEY_OK}, /*play ok */ ++ {0x1be4, KEY_ZOOM}, /*zoom */ ++ {0x59a6, KEY_MUTE}, /*mute */ ++ {0x5ba5, KEY_RADIO}, /*tv/f */ ++ {0x19e7, KEY_RECORD}, /*rec */ ++ {0x01fe, KEY_STOP}, /*Stop */ ++ {0x03fd, KEY_PAUSE}, /*pause */ ++ {0x03fc, KEY_SCREEN}, /*<- -> */ ++ {0x07f9, KEY_CAMERA}, /*capture */ ++ {0x47b9, KEY_ESC}, /*exit */ ++ {0x43bc, KEY_POWER2}, /*power */ + }; + + static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state) +diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c +index 25b43e5..af121db 100644 +--- a/drivers/media/dvb/siano/sms-cards.c ++++ b/drivers/media/dvb/siano/sms-cards.c +@@ -64,7 +64,7 @@ static struct sms_board sms_boards[] = { + .type = SMS_NOVA_B0, + .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", + .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", +- .rc_codes = RC_MAP_RC5_HAUPPAUGE_NEW, ++ .rc_codes = RC_MAP_HAUPPAUGE, + .board_cfg.leds_power = 26, + .board_cfg.led0 = 27, + .board_cfg.led1 = 28, +diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c +index b82756d..1d79ada 100644 +--- a/drivers/media/dvb/ttpci/budget-ci.c ++++ b/drivers/media/dvb/ttpci/budget-ci.c +@@ -26,7 +26,7 @@ + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * +- * the project's page is at http://www.linuxtv.org/ ++ * the project's page is at http://www.linuxtv.org/ + */ + + #include +@@ -102,6 +102,7 @@ struct budget_ci_ir { + int rc5_device; + u32 ir_key; + bool have_command; ++ bool full_rc5; /* Outputs a full RC5 code */ + }; + + struct budget_ci { +@@ -154,11 +155,18 @@ static void msp430_ir_interrupt(unsigned long data) + return; + budget_ci->ir.have_command = false; + +- /* FIXME: We should generate complete scancodes with device info */ + if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && + budget_ci->ir.rc5_device != (command & 0x1f)) + return; + ++ if (budget_ci->ir.full_rc5) { ++ rc_keydown(dev, ++ budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key, ++ (command & 0x20) ? 1 : 0); ++ return; ++ } ++ ++ /* FIXME: We should generate complete scancodes for all devices */ + rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0); + } + +@@ -206,7 +214,8 @@ static int msp430_ir_init(struct budget_ci *budget_ci) + case 0x1011: + case 0x1012: + /* The hauppauge keymap is a superset of these remotes */ +- dev->map_name = RC_MAP_HAUPPAUGE_NEW; ++ dev->map_name = RC_MAP_HAUPPAUGE; ++ budget_ci->ir.full_rc5 = true; + + if (rc5_device < 0) + budget_ci->ir.rc5_device = 0x1f; +diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig +index 1143845..7f03142 100644 +--- a/drivers/media/rc/Kconfig ++++ b/drivers/media/rc/Kconfig +@@ -135,6 +135,19 @@ config IR_MCEUSB + To compile this driver as a module, choose M here: the + module will be called mceusb. + ++config IR_ITE_CIR ++ tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver" ++ depends on PNP ++ depends on RC_CORE ++ ---help--- ++ Say Y here to enable support for integrated infrared receivers ++ /transceivers made by ITE Tech Inc. These are found in ++ several ASUS devices, like the ASUS Digimatrix or the ASUS ++ EEEBox 1501U. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ite-cir. ++ + config IR_NUVOTON + tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" + depends on PNP +diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile +index 67b4f7f..c6cfe70 100644 +--- a/drivers/media/rc/Makefile ++++ b/drivers/media/rc/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o + + # stand-alone IR receivers/transmitters + obj-$(CONFIG_IR_IMON) += imon.o ++obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o + obj-$(CONFIG_IR_MCEUSB) += mceusb.o + obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o + obj-$(CONFIG_IR_ENE) += ene_ir.o +diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c +index e7dc6b4..f714e1a 100644 +--- a/drivers/media/rc/imon.c ++++ b/drivers/media/rc/imon.c +@@ -277,12 +277,21 @@ static const struct { + u64 hw_code; + u32 keycode; + } imon_panel_key_table[] = { +- { 0x000000000f00ffeell, KEY_PROG1 }, /* Go */ ++ { 0x000000000f00ffeell, KEY_MEDIA }, /* Go */ ++ { 0x000000001200ffeell, KEY_UP }, ++ { 0x000000001300ffeell, KEY_DOWN }, ++ { 0x000000001400ffeell, KEY_LEFT }, ++ { 0x000000001500ffeell, KEY_RIGHT }, ++ { 0x000000001600ffeell, KEY_ENTER }, ++ { 0x000000001700ffeell, KEY_ESC }, + { 0x000000001f00ffeell, KEY_AUDIO }, + { 0x000000002000ffeell, KEY_VIDEO }, + { 0x000000002100ffeell, KEY_CAMERA }, + { 0x000000002700ffeell, KEY_DVD }, + { 0x000000002300ffeell, KEY_TV }, ++ { 0x000000002b00ffeell, KEY_EXIT }, ++ { 0x000000002c00ffeell, KEY_SELECT }, ++ { 0x000000002d00ffeell, KEY_MENU }, + { 0x000000000500ffeell, KEY_PREVIOUS }, + { 0x000000000700ffeell, KEY_REWIND }, + { 0x000000000400ffeell, KEY_STOP }, +diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c +index 7b58b4a..63ee722 100644 +--- a/drivers/media/rc/ir-nec-decoder.c ++++ b/drivers/media/rc/ir-nec-decoder.c +@@ -49,6 +49,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) + struct nec_dec *data = &dev->raw->nec; + u32 scancode; + u8 address, not_address, command, not_command; ++ bool send_32bits = false; + + if (!(dev->raw->enabled_protocols & RC_TYPE_NEC)) + return 0; +@@ -164,10 +165,15 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) + if ((command ^ not_command) != 0xff) { + IR_dprintk(1, "NEC checksum error: received 0x%08x\n", + data->bits); +- break; ++ send_32bits = true; + } + +- if ((address ^ not_address) != 0xff) { ++ if (send_32bits) { ++ /* NEC transport, but modified protocol, used by at ++ * least Apple and TiVo remotes */ ++ scancode = data->bits; ++ IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode); ++ } else if ((address ^ not_address) != 0xff) { + /* Extended NEC */ + scancode = address << 16 | + not_address << 8 | +diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c +new file mode 100644 +index 0000000..9be6a83 +--- /dev/null ++++ b/drivers/media/rc/ite-cir.c +@@ -0,0 +1,1736 @@ ++/* ++ * Driver for ITE Tech Inc. IT8712F/IT8512 CIR ++ * ++ * Copyright (C) 2010 Juan Jesús García de Soria ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA. ++ * ++ * Inspired by the original lirc_it87 and lirc_ite8709 drivers, on top of the ++ * skeleton provided by the nuvoton-cir driver. ++ * ++ * The lirc_it87 driver was originally written by Hans-Gunter Lutke Uphues ++ * in 2001, with enhancements by Christoph Bartelmus ++ * , Andrew Calkin and James Edwards ++ * . ++ * ++ * The lirc_ite8709 driver was written by Grégory Lardière ++ * in 2008. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ite-cir.h" ++ ++/* module parameters */ ++ ++/* debug level */ ++static int debug; ++module_param(debug, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(debug, "Enable debugging output"); ++ ++/* low limit for RX carrier freq, Hz, 0 for no RX demodulation */ ++static int rx_low_carrier_freq; ++module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, " ++ "0 for no RX demodulation"); ++ ++/* high limit for RX carrier freq, Hz, 0 for no RX demodulation */ ++static int rx_high_carrier_freq; ++module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, " ++ "Hz, 0 for no RX demodulation"); ++ ++/* override tx carrier frequency */ ++static int tx_carrier_freq; ++module_param(tx_carrier_freq, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(tx_carrier_freq, "Override TX carrier frequency, Hz"); ++ ++/* override tx duty cycle */ ++static int tx_duty_cycle; ++module_param(tx_duty_cycle, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(tx_duty_cycle, "Override TX duty cycle, 1-100"); ++ ++/* override default sample period */ ++static long sample_period; ++module_param(sample_period, long, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(sample_period, "Override carrier sample period, us"); ++ ++/* override detected model id */ ++static int model_number = -1; ++module_param(model_number, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(model_number, "Use this model number, don't autodetect"); ++ ++ ++/* HW-independent code functions */ ++ ++/* check whether carrier frequency is high frequency */ ++static inline bool ite_is_high_carrier_freq(unsigned int freq) ++{ ++ return freq >= ITE_HCF_MIN_CARRIER_FREQ; ++} ++ ++/* get the bits required to program the carrier frequency in CFQ bits, ++ * unshifted */ ++static u8 ite_get_carrier_freq_bits(unsigned int freq) ++{ ++ if (ite_is_high_carrier_freq(freq)) { ++ if (freq < 425000) ++ return ITE_CFQ_400; ++ ++ else if (freq < 465000) ++ return ITE_CFQ_450; ++ ++ else if (freq < 490000) ++ return ITE_CFQ_480; ++ ++ else ++ return ITE_CFQ_500; ++ } else { ++ /* trim to limits */ ++ if (freq < ITE_LCF_MIN_CARRIER_FREQ) ++ freq = ITE_LCF_MIN_CARRIER_FREQ; ++ if (freq > ITE_LCF_MAX_CARRIER_FREQ) ++ freq = ITE_LCF_MAX_CARRIER_FREQ; ++ ++ /* convert to kHz and subtract the base freq */ ++ freq = ++ DIV_ROUND_CLOSEST(freq - ITE_LCF_MIN_CARRIER_FREQ, ++ 1000); ++ ++ return (u8) freq; ++ } ++} ++ ++/* get the bits required to program the pulse with in TXMPW */ ++static u8 ite_get_pulse_width_bits(unsigned int freq, int duty_cycle) ++{ ++ unsigned long period_ns, on_ns; ++ ++ /* sanitize freq into range */ ++ if (freq < ITE_LCF_MIN_CARRIER_FREQ) ++ freq = ITE_LCF_MIN_CARRIER_FREQ; ++ if (freq > ITE_HCF_MAX_CARRIER_FREQ) ++ freq = ITE_HCF_MAX_CARRIER_FREQ; ++ ++ period_ns = 1000000000UL / freq; ++ on_ns = period_ns * duty_cycle / 100; ++ ++ if (ite_is_high_carrier_freq(freq)) { ++ if (on_ns < 750) ++ return ITE_TXMPW_A; ++ ++ else if (on_ns < 850) ++ return ITE_TXMPW_B; ++ ++ else if (on_ns < 950) ++ return ITE_TXMPW_C; ++ ++ else if (on_ns < 1080) ++ return ITE_TXMPW_D; ++ ++ else ++ return ITE_TXMPW_E; ++ } else { ++ if (on_ns < 6500) ++ return ITE_TXMPW_A; ++ ++ else if (on_ns < 7850) ++ return ITE_TXMPW_B; ++ ++ else if (on_ns < 9650) ++ return ITE_TXMPW_C; ++ ++ else if (on_ns < 11950) ++ return ITE_TXMPW_D; ++ ++ else ++ return ITE_TXMPW_E; ++ } ++} ++ ++/* decode raw bytes as received by the hardware, and push them to the ir-core ++ * layer */ ++static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int ++ length) ++{ ++ u32 sample_period; ++ unsigned long *ldata; ++ unsigned int next_one, next_zero, size; ++ DEFINE_IR_RAW_EVENT(ev); ++ ++ if (length == 0) ++ return; ++ ++ sample_period = dev->params.sample_period; ++ ldata = (unsigned long *)data; ++ size = length << 3; ++ next_one = generic_find_next_le_bit(ldata, size, 0); ++ if (next_one > 0) { ++ ev.pulse = true; ++ ev.duration = ++ ITE_BITS_TO_NS(next_one, sample_period); ++ ir_raw_event_store_with_filter(dev->rdev, &ev); ++ } ++ ++ while (next_one < size) { ++ next_zero = generic_find_next_zero_le_bit(ldata, size, next_one + 1); ++ ev.pulse = false; ++ ev.duration = ITE_BITS_TO_NS(next_zero - next_one, sample_period); ++ ir_raw_event_store_with_filter(dev->rdev, &ev); ++ ++ if (next_zero < size) { ++ next_one = ++ generic_find_next_le_bit(ldata, ++ size, ++ next_zero + 1); ++ ev.pulse = true; ++ ev.duration = ++ ITE_BITS_TO_NS(next_one - next_zero, ++ sample_period); ++ ir_raw_event_store_with_filter ++ (dev->rdev, &ev); ++ } else ++ next_one = size; ++ } ++ ++ ir_raw_event_handle(dev->rdev); ++ ++ ite_dbg_verbose("decoded %d bytes.", length); ++} ++ ++/* set all the rx/tx carrier parameters; this must be called with the device ++ * spinlock held */ ++static void ite_set_carrier_params(struct ite_dev *dev) ++{ ++ unsigned int freq, low_freq, high_freq; ++ int allowance; ++ bool use_demodulator; ++ bool for_tx = dev->transmitting; ++ ++ ite_dbg("%s called", __func__); ++ ++ if (for_tx) { ++ /* we don't need no stinking calculations */ ++ freq = dev->params.tx_carrier_freq; ++ allowance = ITE_RXDCR_DEFAULT; ++ use_demodulator = false; ++ } else { ++ low_freq = dev->params.rx_low_carrier_freq; ++ high_freq = dev->params.rx_high_carrier_freq; ++ ++ if (low_freq == 0) { ++ /* don't demodulate */ ++ freq = ++ ITE_DEFAULT_CARRIER_FREQ; ++ allowance = ITE_RXDCR_DEFAULT; ++ use_demodulator = false; ++ } else { ++ /* calculate the middle freq */ ++ freq = (low_freq + high_freq) / 2; ++ ++ /* calculate the allowance */ ++ allowance = ++ DIV_ROUND_CLOSEST(10000 * (high_freq - low_freq), ++ ITE_RXDCR_PER_10000_STEP ++ * (high_freq + low_freq)); ++ ++ if (allowance < 1) ++ allowance = 1; ++ ++ if (allowance > ITE_RXDCR_MAX) ++ allowance = ITE_RXDCR_MAX; ++ } ++ } ++ ++ /* set the carrier parameters in a device-dependent way */ ++ dev->params.set_carrier_params(dev, ite_is_high_carrier_freq(freq), ++ use_demodulator, ite_get_carrier_freq_bits(freq), allowance, ++ ite_get_pulse_width_bits(freq, dev->params.tx_duty_cycle)); ++} ++ ++/* interrupt service routine for incoming and outgoing CIR data */ ++static irqreturn_t ite_cir_isr(int irq, void *data) ++{ ++ struct ite_dev *dev = data; ++ unsigned long flags; ++ irqreturn_t ret = IRQ_RETVAL(IRQ_NONE); ++ u8 rx_buf[ITE_RX_FIFO_LEN]; ++ int rx_bytes; ++ int iflags; ++ ++ ite_dbg_verbose("%s firing", __func__); ++ ++ /* grab the spinlock */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* read the interrupt flags */ ++ iflags = dev->params.get_irq_causes(dev); ++ ++ /* check for the receive interrupt */ ++ if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { ++ /* read the FIFO bytes */ ++ rx_bytes = ++ dev->params.get_rx_bytes(dev, rx_buf, ++ ITE_RX_FIFO_LEN); ++ ++ if (rx_bytes > 0) { ++ /* drop the spinlock, since the ir-core layer ++ * may call us back again through ++ * ite_s_idle() */ ++ spin_unlock_irqrestore(&dev-> ++ lock, ++ flags); ++ ++ /* decode the data we've just received */ ++ ite_decode_bytes(dev, rx_buf, ++ rx_bytes); ++ ++ /* reacquire the spinlock */ ++ spin_lock_irqsave(&dev->lock, ++ flags); ++ ++ /* mark the interrupt as serviced */ ++ ret = IRQ_RETVAL(IRQ_HANDLED); ++ } ++ } else if (iflags & ITE_IRQ_TX_FIFO) { ++ /* FIFO space available interrupt */ ++ ite_dbg_verbose("got interrupt for TX FIFO"); ++ ++ /* wake any sleeping transmitter */ ++ wake_up_interruptible(&dev->tx_queue); ++ ++ /* mark the interrupt as serviced */ ++ ret = IRQ_RETVAL(IRQ_HANDLED); ++ } ++ ++ /* drop the spinlock */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ ite_dbg_verbose("%s done returning %d", __func__, (int)ret); ++ ++ return ret; ++} ++ ++/* set the rx carrier freq range, guess it's in Hz... */ ++static int ite_set_rx_carrier_range(struct rc_dev *rcdev, u32 carrier_low, u32 ++ carrier_high) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.rx_low_carrier_freq = carrier_low; ++ dev->params.rx_high_carrier_freq = carrier_high; ++ ite_set_carrier_params(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++/* set the tx carrier freq, guess it's in Hz... */ ++static int ite_set_tx_carrier(struct rc_dev *rcdev, u32 carrier) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.tx_carrier_freq = carrier; ++ ite_set_carrier_params(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++/* set the tx duty cycle by controlling the pulse width */ ++static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.tx_duty_cycle = duty_cycle; ++ ite_set_carrier_params(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++/* transmit out IR pulses; what you get here is a batch of alternating ++ * pulse/space/pulse/space lengths that we should write out completely through ++ * the FIFO, blocking on a full FIFO */ ++static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ bool is_pulse = false; ++ int remaining_us, fifo_avail, fifo_remaining, last_idx = 0; ++ int max_rle_us, next_rle_us; ++ int ret = n; ++ u8 last_sent[ITE_TX_FIFO_LEN]; ++ u8 val; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* clear the array just in case */ ++ memset(last_sent, 0, ARRAY_SIZE(last_sent)); ++ ++ /* n comes in bytes; convert to ints */ ++ n /= sizeof(int); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* let everybody know we're now transmitting */ ++ dev->transmitting = true; ++ ++ /* and set the carrier values for transmission */ ++ ite_set_carrier_params(dev); ++ ++ /* calculate how much time we can send in one byte */ ++ max_rle_us = ++ (ITE_BAUDRATE_DIVISOR * dev->params.sample_period * ++ ITE_TX_MAX_RLE) / 1000; ++ ++ /* disable the receiver */ ++ dev->params.disable_rx(dev); ++ ++ /* this is where we'll begin filling in the FIFO, until it's full. ++ * then we'll just activate the interrupt, wait for it to wake us up ++ * again, disable it, continue filling the FIFO... until everything ++ * has been pushed out */ ++ fifo_avail = ++ ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); ++ ++ while (n > 0 && dev->in_use) { ++ /* transmit the next sample */ ++ is_pulse = !is_pulse; ++ remaining_us = *(txbuf++); ++ n--; ++ ++ ite_dbg("%s: %ld", ++ ((is_pulse) ? "pulse" : "space"), ++ (long int) ++ remaining_us); ++ ++ /* repeat while the pulse is non-zero length */ ++ while (remaining_us > 0 && dev->in_use) { ++ if (remaining_us > max_rle_us) ++ next_rle_us = max_rle_us; ++ ++ else ++ next_rle_us = remaining_us; ++ ++ remaining_us -= next_rle_us; ++ ++ /* check what's the length we have to pump out */ ++ val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us; ++ ++ /* put it into the sent buffer */ ++ last_sent[last_idx++] = val; ++ last_idx &= (ITE_TX_FIFO_LEN); ++ ++ /* encode it for 7 bits */ ++ val = (val - 1) & ITE_TX_RLE_MASK; ++ ++ /* take into account pulse/space prefix */ ++ if (is_pulse) ++ val |= ITE_TX_PULSE; ++ ++ else ++ val |= ITE_TX_SPACE; ++ ++ /* ++ * if we get to 0 available, read again, just in case ++ * some other slot got freed ++ */ ++ if (fifo_avail <= 0) ++ fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); ++ ++ /* if it's still full */ ++ if (fifo_avail <= 0) { ++ /* enable the tx interrupt */ ++ dev->params. ++ enable_tx_interrupt(dev); ++ ++ /* drop the spinlock */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* wait for the FIFO to empty enough */ ++ wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8); ++ ++ /* get the spinlock again */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable the tx interrupt again. */ ++ dev->params. ++ disable_tx_interrupt(dev); ++ } ++ ++ /* now send the byte through the FIFO */ ++ dev->params.put_tx_byte(dev, val); ++ fifo_avail--; ++ } ++ } ++ ++ /* wait and don't return until the whole FIFO has been sent out; ++ * otherwise we could configure the RX carrier params instead of the ++ * TX ones while the transmission is still being performed! */ ++ fifo_remaining = dev->params.get_tx_used_slots(dev); ++ remaining_us = 0; ++ while (fifo_remaining > 0) { ++ fifo_remaining--; ++ last_idx--; ++ last_idx &= (ITE_TX_FIFO_LEN - 1); ++ remaining_us += last_sent[last_idx]; ++ } ++ remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE); ++ ++ /* drop the spinlock while we sleep */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* sleep remaining_us microseconds */ ++ mdelay(DIV_ROUND_UP(remaining_us, 1000)); ++ ++ /* reacquire the spinlock */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* now we're not transmitting anymore */ ++ dev->transmitting = false; ++ ++ /* and set the carrier values for reception */ ++ ite_set_carrier_params(dev); ++ ++ /* reenable the receiver */ ++ if (dev->in_use) ++ dev->params.enable_rx(dev); ++ ++ /* notify transmission end */ ++ wake_up_interruptible(&dev->tx_ended); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return ret; ++} ++ ++/* idle the receiver if needed */ ++static void ite_s_idle(struct rc_dev *rcdev, bool enable) ++{ ++ unsigned long flags; ++ struct ite_dev *dev = rcdev->priv; ++ ++ ite_dbg("%s called", __func__); ++ ++ if (enable) { ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->params.idle_rx(dev); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ } ++} ++ ++ ++/* IT8712F HW-specific functions */ ++ ++/* retrieve a bitmask of the current causes for a pending interrupt; this may ++ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN ++ * */ ++static int it87_get_irq_causes(struct ite_dev *dev) ++{ ++ u8 iflags; ++ int ret = 0; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* read the interrupt flags */ ++ iflags = inb(dev->cir_addr + IT87_IIR) & IT87_II; ++ ++ switch (iflags) { ++ case IT87_II_RXDS: ++ ret = ITE_IRQ_RX_FIFO; ++ break; ++ case IT87_II_RXFO: ++ ret = ITE_IRQ_RX_FIFO_OVERRUN; ++ break; ++ case IT87_II_TXLDL: ++ ret = ITE_IRQ_TX_FIFO; ++ break; ++ } ++ ++ return ret; ++} ++ ++/* set the carrier parameters; to be called with the spinlock held */ ++static void it87_set_carrier_params(struct ite_dev *dev, bool high_freq, ++ bool use_demodulator, ++ u8 carrier_freq_bits, u8 allowance_bits, ++ u8 pulse_width_bits) ++{ ++ u8 val; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* program the RCR register */ ++ val = inb(dev->cir_addr + IT87_RCR) ++ & ~(IT87_HCFS | IT87_RXEND | IT87_RXDCR); ++ ++ if (high_freq) ++ val |= IT87_HCFS; ++ ++ if (use_demodulator) ++ val |= IT87_RXEND; ++ ++ val |= allowance_bits; ++ ++ outb(val, dev->cir_addr + IT87_RCR); ++ ++ /* program the TCR2 register */ ++ outb((carrier_freq_bits << IT87_CFQ_SHIFT) | pulse_width_bits, ++ dev->cir_addr + IT87_TCR2); ++} ++ ++/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock ++ * held */ ++static int it87_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size) ++{ ++ int fifo, read = 0; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* read how many bytes are still in the FIFO */ ++ fifo = inb(dev->cir_addr + IT87_RSR) & IT87_RXFBC; ++ ++ while (fifo > 0 && buf_size > 0) { ++ *(buf++) = inb(dev->cir_addr + IT87_DR); ++ fifo--; ++ read++; ++ buf_size--; ++ } ++ ++ return read; ++} ++ ++/* return how many bytes are still in the FIFO; this will be called ++ * with the device spinlock NOT HELD while waiting for the TX FIFO to get ++ * empty; let's expect this won't be a problem */ ++static int it87_get_tx_used_slots(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ return inb(dev->cir_addr + IT87_TSR) & IT87_TXFBC; ++} ++ ++/* put a byte to the TX fifo; this should be called with the spinlock held */ ++static void it87_put_tx_byte(struct ite_dev *dev, u8 value) ++{ ++ outb(value, dev->cir_addr + IT87_DR); ++} ++ ++/* idle the receiver so that we won't receive samples until another ++ pulse is detected; this must be called with the device spinlock held */ ++static void it87_idle_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable streaming by clearing RXACT writing it as 1 */ ++ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXACT, ++ dev->cir_addr + IT87_RCR); ++ ++ /* clear the FIFO */ ++ outb(inb(dev->cir_addr + IT87_TCR1) | IT87_FIFOCLR, ++ dev->cir_addr + IT87_TCR1); ++} ++ ++/* disable the receiver; this must be called with the device spinlock held */ ++static void it87_disable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the receiver interrupts */ ++ outb(inb(dev->cir_addr + IT87_IER) & ~(IT87_RDAIE | IT87_RFOIE), ++ dev->cir_addr + IT87_IER); ++ ++ /* disable the receiver */ ++ outb(inb(dev->cir_addr + IT87_RCR) & ~IT87_RXEN, ++ dev->cir_addr + IT87_RCR); ++ ++ /* clear the FIFO and RXACT (actually RXACT should have been cleared ++ * in the previous outb() call) */ ++ it87_idle_rx(dev); ++} ++ ++/* enable the receiver; this must be called with the device spinlock held */ ++static void it87_enable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the receiver by setting RXEN */ ++ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXEN, ++ dev->cir_addr + IT87_RCR); ++ ++ /* just prepare it to idle for the next reception */ ++ it87_idle_rx(dev); ++ ++ /* enable the receiver interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT87_IER) | IT87_RDAIE | IT87_RFOIE | IT87_IEC, ++ dev->cir_addr + IT87_IER); ++} ++ ++/* disable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it87_disable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the transmitter interrupts */ ++ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_TLDLIE, ++ dev->cir_addr + IT87_IER); ++} ++ ++/* enable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it87_enable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the transmitter interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT87_IER) | IT87_TLDLIE | IT87_IEC, ++ dev->cir_addr + IT87_IER); ++} ++ ++/* disable the device; this must be called with the device spinlock held */ ++static void it87_disable(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* clear out all interrupt enable flags */ ++ outb(inb(dev->cir_addr + IT87_IER) & ++ ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE), ++ dev->cir_addr + IT87_IER); ++ ++ /* disable the receiver */ ++ it87_disable_rx(dev); ++ ++ /* erase the FIFO */ ++ outb(IT87_FIFOCLR | inb(dev->cir_addr + IT87_TCR1), ++ dev->cir_addr + IT87_TCR1); ++} ++ ++/* initialize the hardware */ ++static void it87_init_hardware(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable just the baud rate divisor register, ++ disabling all the interrupts at the same time */ ++ outb((inb(dev->cir_addr + IT87_IER) & ++ ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE)) | IT87_BR, ++ dev->cir_addr + IT87_IER); ++ ++ /* write out the baud rate divisor */ ++ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR); ++ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR); ++ ++ /* disable the baud rate divisor register again */ ++ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR, ++ dev->cir_addr + IT87_IER); ++ ++ /* program the RCR register defaults */ ++ outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR); ++ ++ /* program the TCR1 register */ ++ outb(IT87_TXMPM_DEFAULT | IT87_TXENDF | IT87_TXRLE ++ | IT87_FIFOTL_DEFAULT | IT87_FIFOCLR, ++ dev->cir_addr + IT87_TCR1); ++ ++ /* program the carrier parameters */ ++ ite_set_carrier_params(dev); ++} ++ ++/* IT8512F on ITE8708 HW-specific functions */ ++ ++/* retrieve a bitmask of the current causes for a pending interrupt; this may ++ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN ++ * */ ++static int it8708_get_irq_causes(struct ite_dev *dev) ++{ ++ u8 iflags; ++ int ret = 0; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* read the interrupt flags */ ++ iflags = inb(dev->cir_addr + IT8708_C0IIR); ++ ++ if (iflags & IT85_TLDLI) ++ ret |= ITE_IRQ_TX_FIFO; ++ if (iflags & IT85_RDAI) ++ ret |= ITE_IRQ_RX_FIFO; ++ if (iflags & IT85_RFOI) ++ ret |= ITE_IRQ_RX_FIFO_OVERRUN; ++ ++ return ret; ++} ++ ++/* set the carrier parameters; to be called with the spinlock held */ ++static void it8708_set_carrier_params(struct ite_dev *dev, bool high_freq, ++ bool use_demodulator, ++ u8 carrier_freq_bits, u8 allowance_bits, ++ u8 pulse_width_bits) ++{ ++ u8 val; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* program the C0CFR register, with HRAE=1 */ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE, ++ dev->cir_addr + IT8708_BANKSEL); ++ ++ val = (inb(dev->cir_addr + IT8708_C0CFR) ++ & ~(IT85_HCFS | IT85_CFQ)) | carrier_freq_bits; ++ ++ if (high_freq) ++ val |= IT85_HCFS; ++ ++ outb(val, dev->cir_addr + IT8708_C0CFR); ++ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE, ++ dev->cir_addr + IT8708_BANKSEL); ++ ++ /* program the C0RCR register */ ++ val = inb(dev->cir_addr + IT8708_C0RCR) ++ & ~(IT85_RXEND | IT85_RXDCR); ++ ++ if (use_demodulator) ++ val |= IT85_RXEND; ++ ++ val |= allowance_bits; ++ ++ outb(val, dev->cir_addr + IT8708_C0RCR); ++ ++ /* program the C0TCR register */ ++ val = inb(dev->cir_addr + IT8708_C0TCR) & ~IT85_TXMPW; ++ val |= pulse_width_bits; ++ outb(val, dev->cir_addr + IT8708_C0TCR); ++} ++ ++/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock ++ * held */ ++static int it8708_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size) ++{ ++ int fifo, read = 0; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* read how many bytes are still in the FIFO */ ++ fifo = inb(dev->cir_addr + IT8708_C0RFSR) & IT85_RXFBC; ++ ++ while (fifo > 0 && buf_size > 0) { ++ *(buf++) = inb(dev->cir_addr + IT8708_C0DR); ++ fifo--; ++ read++; ++ buf_size--; ++ } ++ ++ return read; ++} ++ ++/* return how many bytes are still in the FIFO; this will be called ++ * with the device spinlock NOT HELD while waiting for the TX FIFO to get ++ * empty; let's expect this won't be a problem */ ++static int it8708_get_tx_used_slots(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ return inb(dev->cir_addr + IT8708_C0TFSR) & IT85_TXFBC; ++} ++ ++/* put a byte to the TX fifo; this should be called with the spinlock held */ ++static void it8708_put_tx_byte(struct ite_dev *dev, u8 value) ++{ ++ outb(value, dev->cir_addr + IT8708_C0DR); ++} ++ ++/* idle the receiver so that we won't receive samples until another ++ pulse is detected; this must be called with the device spinlock held */ ++static void it8708_idle_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable streaming by clearing RXACT writing it as 1 */ ++ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXACT, ++ dev->cir_addr + IT8708_C0RCR); ++ ++ /* clear the FIFO */ ++ outb(inb(dev->cir_addr + IT8708_C0MSTCR) | IT85_FIFOCLR, ++ dev->cir_addr + IT8708_C0MSTCR); ++} ++ ++/* disable the receiver; this must be called with the device spinlock held */ ++static void it8708_disable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the receiver interrupts */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ++ ~(IT85_RDAIE | IT85_RFOIE), ++ dev->cir_addr + IT8708_C0IER); ++ ++ /* disable the receiver */ ++ outb(inb(dev->cir_addr + IT8708_C0RCR) & ~IT85_RXEN, ++ dev->cir_addr + IT8708_C0RCR); ++ ++ /* clear the FIFO and RXACT (actually RXACT should have been cleared ++ * in the previous outb() call) */ ++ it8708_idle_rx(dev); ++} ++ ++/* enable the receiver; this must be called with the device spinlock held */ ++static void it8708_enable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the receiver by setting RXEN */ ++ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXEN, ++ dev->cir_addr + IT8708_C0RCR); ++ ++ /* just prepare it to idle for the next reception */ ++ it8708_idle_rx(dev); ++ ++ /* enable the receiver interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) ++ |IT85_RDAIE | IT85_RFOIE | IT85_IEC, ++ dev->cir_addr + IT8708_C0IER); ++} ++ ++/* disable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it8708_disable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the transmitter interrupts */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ~IT85_TLDLIE, ++ dev->cir_addr + IT8708_C0IER); ++} ++ ++/* enable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it8708_enable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the transmitter interrupts and master enable flag */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) ++ |IT85_TLDLIE | IT85_IEC, ++ dev->cir_addr + IT8708_C0IER); ++} ++ ++/* disable the device; this must be called with the device spinlock held */ ++static void it8708_disable(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* clear out all interrupt enable flags */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ++ ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), ++ dev->cir_addr + IT8708_C0IER); ++ ++ /* disable the receiver */ ++ it8708_disable_rx(dev); ++ ++ /* erase the FIFO */ ++ outb(IT85_FIFOCLR | inb(dev->cir_addr + IT8708_C0MSTCR), ++ dev->cir_addr + IT8708_C0MSTCR); ++} ++ ++/* initialize the hardware */ ++static void it8708_init_hardware(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable all the interrupts */ ++ outb(inb(dev->cir_addr + IT8708_C0IER) & ++ ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), ++ dev->cir_addr + IT8708_C0IER); ++ ++ /* program the baud rate divisor */ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE, ++ dev->cir_addr + IT8708_BANKSEL); ++ ++ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT8708_C0BDLR); ++ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, ++ dev->cir_addr + IT8708_C0BDHR); ++ ++ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE, ++ dev->cir_addr + IT8708_BANKSEL); ++ ++ /* program the C0MSTCR register defaults */ ++ outb((inb(dev->cir_addr + IT8708_C0MSTCR) & ++ ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL | ++ IT85_FIFOCLR | IT85_RESET)) | ++ IT85_FIFOTL_DEFAULT, ++ dev->cir_addr + IT8708_C0MSTCR); ++ ++ /* program the C0RCR register defaults */ ++ outb((inb(dev->cir_addr + IT8708_C0RCR) & ++ ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | ++ IT85_RXACT | IT85_RXDCR)) | ++ ITE_RXDCR_DEFAULT, ++ dev->cir_addr + IT8708_C0RCR); ++ ++ /* program the C0TCR register defaults */ ++ outb((inb(dev->cir_addr + IT8708_C0TCR) & ++ ~(IT85_TXMPM | IT85_TXMPW)) ++ |IT85_TXRLE | IT85_TXENDF | ++ IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT, ++ dev->cir_addr + IT8708_C0TCR); ++ ++ /* program the carrier parameters */ ++ ite_set_carrier_params(dev); ++} ++ ++/* IT8512F on ITE8709 HW-specific functions */ ++ ++/* read a byte from the SRAM module */ ++static inline u8 it8709_rm(struct ite_dev *dev, int index) ++{ ++ outb(index, dev->cir_addr + IT8709_RAM_IDX); ++ return inb(dev->cir_addr + IT8709_RAM_VAL); ++} ++ ++/* write a byte to the SRAM module */ ++static inline void it8709_wm(struct ite_dev *dev, u8 val, int index) ++{ ++ outb(index, dev->cir_addr + IT8709_RAM_IDX); ++ outb(val, dev->cir_addr + IT8709_RAM_VAL); ++} ++ ++static void it8709_wait(struct ite_dev *dev) ++{ ++ int i = 0; ++ /* ++ * loop until device tells it's ready to continue ++ * iterations count is usually ~750 but can sometimes achieve 13000 ++ */ ++ for (i = 0; i < 15000; i++) { ++ udelay(2); ++ if (it8709_rm(dev, IT8709_MODE) == IT8709_IDLE) ++ break; ++ } ++} ++ ++/* read the value of a CIR register */ ++static u8 it8709_rr(struct ite_dev *dev, int index) ++{ ++ /* just wait in case the previous access was a write */ ++ it8709_wait(dev); ++ it8709_wm(dev, index, IT8709_REG_IDX); ++ it8709_wm(dev, IT8709_READ, IT8709_MODE); ++ ++ /* wait for the read data to be available */ ++ it8709_wait(dev); ++ ++ /* return the read value */ ++ return it8709_rm(dev, IT8709_REG_VAL); ++} ++ ++/* write the value of a CIR register */ ++static void it8709_wr(struct ite_dev *dev, u8 val, int index) ++{ ++ /* we wait before writing, and not afterwards, since this allows us to ++ * pipeline the host CPU with the microcontroller */ ++ it8709_wait(dev); ++ it8709_wm(dev, val, IT8709_REG_VAL); ++ it8709_wm(dev, index, IT8709_REG_IDX); ++ it8709_wm(dev, IT8709_WRITE, IT8709_MODE); ++} ++ ++/* retrieve a bitmask of the current causes for a pending interrupt; this may ++ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN ++ * */ ++static int it8709_get_irq_causes(struct ite_dev *dev) ++{ ++ u8 iflags; ++ int ret = 0; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* read the interrupt flags */ ++ iflags = it8709_rm(dev, IT8709_IIR); ++ ++ if (iflags & IT85_TLDLI) ++ ret |= ITE_IRQ_TX_FIFO; ++ if (iflags & IT85_RDAI) ++ ret |= ITE_IRQ_RX_FIFO; ++ if (iflags & IT85_RFOI) ++ ret |= ITE_IRQ_RX_FIFO_OVERRUN; ++ ++ return ret; ++} ++ ++/* set the carrier parameters; to be called with the spinlock held */ ++static void it8709_set_carrier_params(struct ite_dev *dev, bool high_freq, ++ bool use_demodulator, ++ u8 carrier_freq_bits, u8 allowance_bits, ++ u8 pulse_width_bits) ++{ ++ u8 val; ++ ++ ite_dbg("%s called", __func__); ++ ++ val = (it8709_rr(dev, IT85_C0CFR) ++ &~(IT85_HCFS | IT85_CFQ)) | ++ carrier_freq_bits; ++ ++ if (high_freq) ++ val |= IT85_HCFS; ++ ++ it8709_wr(dev, val, IT85_C0CFR); ++ ++ /* program the C0RCR register */ ++ val = it8709_rr(dev, IT85_C0RCR) ++ & ~(IT85_RXEND | IT85_RXDCR); ++ ++ if (use_demodulator) ++ val |= IT85_RXEND; ++ ++ val |= allowance_bits; ++ ++ it8709_wr(dev, val, IT85_C0RCR); ++ ++ /* program the C0TCR register */ ++ val = it8709_rr(dev, IT85_C0TCR) & ~IT85_TXMPW; ++ val |= pulse_width_bits; ++ it8709_wr(dev, val, IT85_C0TCR); ++} ++ ++/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock ++ * held */ ++static int it8709_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size) ++{ ++ int fifo, read = 0; ++ ++ ite_dbg("%s called", __func__); ++ ++ /* read how many bytes are still in the FIFO */ ++ fifo = it8709_rm(dev, IT8709_RFSR) & IT85_RXFBC; ++ ++ while (fifo > 0 && buf_size > 0) { ++ *(buf++) = it8709_rm(dev, IT8709_FIFO + read); ++ fifo--; ++ read++; ++ buf_size--; ++ } ++ ++ /* 'clear' the FIFO by setting the writing index to 0; this is ++ * completely bound to be racy, but we can't help it, since it's a ++ * limitation of the protocol */ ++ it8709_wm(dev, 0, IT8709_RFSR); ++ ++ return read; ++} ++ ++/* return how many bytes are still in the FIFO; this will be called ++ * with the device spinlock NOT HELD while waiting for the TX FIFO to get ++ * empty; let's expect this won't be a problem */ ++static int it8709_get_tx_used_slots(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ return it8709_rr(dev, IT85_C0TFSR) & IT85_TXFBC; ++} ++ ++/* put a byte to the TX fifo; this should be called with the spinlock held */ ++static void it8709_put_tx_byte(struct ite_dev *dev, u8 value) ++{ ++ it8709_wr(dev, value, IT85_C0DR); ++} ++ ++/* idle the receiver so that we won't receive samples until another ++ pulse is detected; this must be called with the device spinlock held */ ++static void it8709_idle_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable streaming by clearing RXACT writing it as 1 */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXACT, ++ IT85_C0RCR); ++ ++ /* clear the FIFO */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0MSTCR) | IT85_FIFOCLR, ++ IT85_C0MSTCR); ++} ++ ++/* disable the receiver; this must be called with the device spinlock held */ ++static void it8709_disable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the receiver interrupts */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ++ ~(IT85_RDAIE | IT85_RFOIE), ++ IT85_C0IER); ++ ++ /* disable the receiver */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) & ~IT85_RXEN, ++ IT85_C0RCR); ++ ++ /* clear the FIFO and RXACT (actually RXACT should have been cleared ++ * in the previous it8709_wr(dev, ) call) */ ++ it8709_idle_rx(dev); ++} ++ ++/* enable the receiver; this must be called with the device spinlock held */ ++static void it8709_enable_rx(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the receiver by setting RXEN */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXEN, ++ IT85_C0RCR); ++ ++ /* just prepare it to idle for the next reception */ ++ it8709_idle_rx(dev); ++ ++ /* enable the receiver interrupts and master enable flag */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) ++ |IT85_RDAIE | IT85_RFOIE | IT85_IEC, ++ IT85_C0IER); ++} ++ ++/* disable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it8709_disable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable the transmitter interrupts */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ~IT85_TLDLIE, ++ IT85_C0IER); ++} ++ ++/* enable the transmitter interrupt; this must be called with the device ++ * spinlock held */ ++static void it8709_enable_tx_interrupt(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* enable the transmitter interrupts and master enable flag */ ++ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) ++ |IT85_TLDLIE | IT85_IEC, ++ IT85_C0IER); ++} ++ ++/* disable the device; this must be called with the device spinlock held */ ++static void it8709_disable(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* clear out all interrupt enable flags */ ++ it8709_wr(dev, ++ it8709_rr(dev, ++ IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | ++ IT85_RDAIE | ++ IT85_TLDLIE), IT85_C0IER); ++ ++ /* disable the receiver */ ++ it8709_disable_rx(dev); ++ ++ /* erase the FIFO */ ++ it8709_wr(dev, IT85_FIFOCLR | it8709_rr(dev, IT85_C0MSTCR), ++ IT85_C0MSTCR); ++} ++ ++/* initialize the hardware */ ++static void it8709_init_hardware(struct ite_dev *dev) ++{ ++ ite_dbg("%s called", __func__); ++ ++ /* disable all the interrupts */ ++ it8709_wr(dev, ++ it8709_rr(dev, ++ IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | ++ IT85_RDAIE | ++ IT85_TLDLIE), IT85_C0IER); ++ ++ /* program the baud rate divisor */ ++ it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR); ++ it8709_wr(dev, (ITE_BAUDRATE_DIVISOR >> 8) & 0xff, ++ IT85_C0BDHR); ++ ++ /* program the C0MSTCR register defaults */ ++ it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL | ++ IT85_ILE ++ | IT85_FIFOTL ++ | ++ IT85_FIFOCLR ++ | ++ IT85_RESET)) ++ | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR); ++ ++ /* program the C0RCR register defaults */ ++ it8709_wr(dev, ++ (it8709_rr(dev, IT85_C0RCR) & ++ ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND ++ | IT85_RXACT | IT85_RXDCR)) | ++ ITE_RXDCR_DEFAULT, IT85_C0RCR); ++ ++ /* program the C0TCR register defaults */ ++ it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) ++ &~(IT85_TXMPM | IT85_TXMPW)) ++ |IT85_TXRLE | IT85_TXENDF | ++ IT85_TXMPM_DEFAULT | ++ IT85_TXMPW_DEFAULT, IT85_C0TCR); ++ ++ /* program the carrier parameters */ ++ ite_set_carrier_params(dev); ++} ++ ++ ++/* generic hardware setup/teardown code */ ++ ++/* activate the device for use */ ++static int ite_open(struct rc_dev *rcdev) ++{ ++ struct ite_dev *dev = rcdev->priv; ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->in_use = true; ++ ++ /* enable the receiver */ ++ dev->params.enable_rx(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++/* deactivate the device for use */ ++static void ite_close(struct rc_dev *rcdev) ++{ ++ struct ite_dev *dev = rcdev->priv; ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->in_use = false; ++ ++ /* wait for any transmission to end */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ wait_event_interruptible(dev->tx_ended, !dev->transmitting); ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++/* supported models and their parameters */ ++static const struct ite_dev_params ite_dev_descs[] = { ++ { /* 0: ITE8704 */ ++ .model = "ITE8704 CIR transceiver", ++ .io_region_size = IT87_IOREG_LENGTH, ++ .hw_tx_capable = true, ++ .sample_period = (u32) (1000000000ULL / 115200), ++ .tx_carrier_freq = 38000, ++ .tx_duty_cycle = 33, ++ .rx_low_carrier_freq = 0, ++ .rx_high_carrier_freq = 0, ++ ++ /* operations */ ++ .get_irq_causes = it87_get_irq_causes, ++ .enable_rx = it87_enable_rx, ++ .idle_rx = it87_idle_rx, ++ .disable_rx = it87_idle_rx, ++ .get_rx_bytes = it87_get_rx_bytes, ++ .enable_tx_interrupt = it87_enable_tx_interrupt, ++ .disable_tx_interrupt = it87_disable_tx_interrupt, ++ .get_tx_used_slots = it87_get_tx_used_slots, ++ .put_tx_byte = it87_put_tx_byte, ++ .disable = it87_disable, ++ .init_hardware = it87_init_hardware, ++ .set_carrier_params = it87_set_carrier_params, ++ }, ++ { /* 1: ITE8713 */ ++ .model = "ITE8713 CIR transceiver", ++ .io_region_size = IT87_IOREG_LENGTH, ++ .hw_tx_capable = true, ++ .sample_period = (u32) (1000000000ULL / 115200), ++ .tx_carrier_freq = 38000, ++ .tx_duty_cycle = 33, ++ .rx_low_carrier_freq = 0, ++ .rx_high_carrier_freq = 0, ++ ++ /* operations */ ++ .get_irq_causes = it87_get_irq_causes, ++ .enable_rx = it87_enable_rx, ++ .idle_rx = it87_idle_rx, ++ .disable_rx = it87_idle_rx, ++ .get_rx_bytes = it87_get_rx_bytes, ++ .enable_tx_interrupt = it87_enable_tx_interrupt, ++ .disable_tx_interrupt = it87_disable_tx_interrupt, ++ .get_tx_used_slots = it87_get_tx_used_slots, ++ .put_tx_byte = it87_put_tx_byte, ++ .disable = it87_disable, ++ .init_hardware = it87_init_hardware, ++ .set_carrier_params = it87_set_carrier_params, ++ }, ++ { /* 2: ITE8708 */ ++ .model = "ITE8708 CIR transceiver", ++ .io_region_size = IT8708_IOREG_LENGTH, ++ .hw_tx_capable = true, ++ .sample_period = (u32) (1000000000ULL / 115200), ++ .tx_carrier_freq = 38000, ++ .tx_duty_cycle = 33, ++ .rx_low_carrier_freq = 0, ++ .rx_high_carrier_freq = 0, ++ ++ /* operations */ ++ .get_irq_causes = it8708_get_irq_causes, ++ .enable_rx = it8708_enable_rx, ++ .idle_rx = it8708_idle_rx, ++ .disable_rx = it8708_idle_rx, ++ .get_rx_bytes = it8708_get_rx_bytes, ++ .enable_tx_interrupt = it8708_enable_tx_interrupt, ++ .disable_tx_interrupt = ++ it8708_disable_tx_interrupt, ++ .get_tx_used_slots = it8708_get_tx_used_slots, ++ .put_tx_byte = it8708_put_tx_byte, ++ .disable = it8708_disable, ++ .init_hardware = it8708_init_hardware, ++ .set_carrier_params = it8708_set_carrier_params, ++ }, ++ { /* 3: ITE8709 */ ++ .model = "ITE8709 CIR transceiver", ++ .io_region_size = IT8709_IOREG_LENGTH, ++ .hw_tx_capable = true, ++ .sample_period = (u32) (1000000000ULL / 115200), ++ .tx_carrier_freq = 38000, ++ .tx_duty_cycle = 33, ++ .rx_low_carrier_freq = 0, ++ .rx_high_carrier_freq = 0, ++ ++ /* operations */ ++ .get_irq_causes = it8709_get_irq_causes, ++ .enable_rx = it8709_enable_rx, ++ .idle_rx = it8709_idle_rx, ++ .disable_rx = it8709_idle_rx, ++ .get_rx_bytes = it8709_get_rx_bytes, ++ .enable_tx_interrupt = it8709_enable_tx_interrupt, ++ .disable_tx_interrupt = ++ it8709_disable_tx_interrupt, ++ .get_tx_used_slots = it8709_get_tx_used_slots, ++ .put_tx_byte = it8709_put_tx_byte, ++ .disable = it8709_disable, ++ .init_hardware = it8709_init_hardware, ++ .set_carrier_params = it8709_set_carrier_params, ++ }, ++}; ++ ++static const struct pnp_device_id ite_ids[] = { ++ {"ITE8704", 0}, /* Default model */ ++ {"ITE8713", 1}, /* CIR found in EEEBox 1501U */ ++ {"ITE8708", 2}, /* Bridged IT8512 */ ++ {"ITE8709", 3}, /* SRAM-Bridged IT8512 */ ++ {"", 0}, ++}; ++ ++/* allocate memory, probe hardware, and initialize everything */ ++static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id ++ *dev_id) ++{ ++ const struct ite_dev_params *dev_desc = NULL; ++ struct ite_dev *itdev = NULL; ++ struct rc_dev *rdev = NULL; ++ int ret = -ENOMEM; ++ int model_no; ++ ++ ite_dbg("%s called", __func__); ++ ++ itdev = kzalloc(sizeof(struct ite_dev), GFP_KERNEL); ++ if (!itdev) ++ return ret; ++ ++ /* input device for IR remote (and tx) */ ++ rdev = rc_allocate_device(); ++ if (!rdev) ++ goto failure; ++ ++ ret = -ENODEV; ++ ++ /* get the model number */ ++ model_no = (int)dev_id->driver_data; ++ ite_pr(KERN_NOTICE, "Auto-detected model: %s\n", ++ ite_dev_descs[model_no].model); ++ ++ if (model_number >= 0 && model_number < ARRAY_SIZE(ite_dev_descs)) { ++ model_no = model_number; ++ ite_pr(KERN_NOTICE, "The model has been fixed by a module " ++ "parameter."); ++ } ++ ++ ite_pr(KERN_NOTICE, "Using model: %s\n", ite_dev_descs[model_no].model); ++ ++ /* get the description for the device */ ++ dev_desc = &ite_dev_descs[model_no]; ++ ++ /* validate pnp resources */ ++ if (!pnp_port_valid(pdev, 0) || ++ pnp_port_len(pdev, 0) != dev_desc->io_region_size) { ++ dev_err(&pdev->dev, "IR PNP Port not valid!\n"); ++ goto failure; ++ } ++ ++ if (!pnp_irq_valid(pdev, 0)) { ++ dev_err(&pdev->dev, "PNP IRQ not valid!\n"); ++ goto failure; ++ } ++ ++ /* store resource values */ ++ itdev->cir_addr = pnp_port_start(pdev, 0); ++ itdev->cir_irq = pnp_irq(pdev, 0); ++ ++ /* initialize spinlocks */ ++ spin_lock_init(&itdev->lock); ++ ++ /* initialize raw event */ ++ init_ir_raw_event(&itdev->rawir); ++ ++ ret = -EBUSY; ++ /* now claim resources */ ++ if (!request_region(itdev->cir_addr, ++ dev_desc->io_region_size, ITE_DRIVER_NAME)) ++ goto failure; ++ ++ if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED, ++ ITE_DRIVER_NAME, (void *)itdev)) ++ goto failure; ++ ++ /* set driver data into the pnp device */ ++ pnp_set_drvdata(pdev, itdev); ++ itdev->pdev = pdev; ++ ++ /* initialize waitqueues for transmission */ ++ init_waitqueue_head(&itdev->tx_queue); ++ init_waitqueue_head(&itdev->tx_ended); ++ ++ /* copy model-specific parameters */ ++ itdev->params = *dev_desc; ++ ++ /* apply any overrides */ ++ if (sample_period > 0) ++ itdev->params.sample_period = sample_period; ++ ++ if (tx_carrier_freq > 0) ++ itdev->params.tx_carrier_freq = tx_carrier_freq; ++ ++ if (tx_duty_cycle > 0 && tx_duty_cycle <= 100) ++ itdev->params.tx_duty_cycle = tx_duty_cycle; ++ ++ if (rx_low_carrier_freq > 0) ++ itdev->params.rx_low_carrier_freq = rx_low_carrier_freq; ++ ++ if (rx_high_carrier_freq > 0) ++ itdev->params.rx_high_carrier_freq = rx_high_carrier_freq; ++ ++ /* print out parameters */ ++ ite_pr(KERN_NOTICE, "TX-capable: %d\n", (int) ++ itdev->params.hw_tx_capable); ++ ite_pr(KERN_NOTICE, "Sample period (ns): %ld\n", (long) ++ itdev->params.sample_period); ++ ite_pr(KERN_NOTICE, "TX carrier frequency (Hz): %d\n", (int) ++ itdev->params.tx_carrier_freq); ++ ite_pr(KERN_NOTICE, "TX duty cycle (%%): %d\n", (int) ++ itdev->params.tx_duty_cycle); ++ ite_pr(KERN_NOTICE, "RX low carrier frequency (Hz): %d\n", (int) ++ itdev->params.rx_low_carrier_freq); ++ ite_pr(KERN_NOTICE, "RX high carrier frequency (Hz): %d\n", (int) ++ itdev->params.rx_high_carrier_freq); ++ ++ /* set up hardware initial state */ ++ itdev->params.init_hardware(itdev); ++ ++ /* set up ir-core props */ ++ rdev->priv = itdev; ++ rdev->driver_type = RC_DRIVER_IR_RAW; ++ rdev->allowed_protos = RC_TYPE_ALL; ++ rdev->open = ite_open; ++ rdev->close = ite_close; ++ rdev->s_idle = ite_s_idle; ++ rdev->s_rx_carrier_range = ite_set_rx_carrier_range; ++ rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT; ++ rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT; ++ rdev->timeout = ITE_IDLE_TIMEOUT; ++ rdev->rx_resolution = ITE_BAUDRATE_DIVISOR * ++ itdev->params.sample_period; ++ rdev->tx_resolution = ITE_BAUDRATE_DIVISOR * ++ itdev->params.sample_period; ++ ++ /* set up transmitter related values if needed */ ++ if (itdev->params.hw_tx_capable) { ++ rdev->tx_ir = ite_tx_ir; ++ rdev->s_tx_carrier = ite_set_tx_carrier; ++ rdev->s_tx_duty_cycle = ite_set_tx_duty_cycle; ++ } ++ ++ rdev->input_name = dev_desc->model; ++ rdev->input_id.bustype = BUS_HOST; ++ rdev->input_id.vendor = PCI_VENDOR_ID_ITE; ++ rdev->input_id.product = 0; ++ rdev->input_id.version = 0; ++ rdev->driver_name = ITE_DRIVER_NAME; ++ rdev->map_name = RC_MAP_RC6_MCE; ++ ++ ret = rc_register_device(rdev); ++ if (ret) ++ goto failure; ++ ++ itdev->rdev = rdev; ++ ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); ++ ++ return 0; ++ ++failure: ++ if (itdev->cir_irq) ++ free_irq(itdev->cir_irq, itdev); ++ ++ if (itdev->cir_addr) ++ release_region(itdev->cir_addr, itdev->params.io_region_size); ++ ++ rc_free_device(rdev); ++ kfree(itdev); ++ ++ return ret; ++} ++ ++static void __devexit ite_remove(struct pnp_dev *pdev) ++{ ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable hardware */ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ /* free resources */ ++ free_irq(dev->cir_irq, dev); ++ release_region(dev->cir_addr, dev->params.io_region_size); ++ ++ rc_unregister_device(dev->rdev); ++ ++ kfree(dev); ++} ++ ++static int ite_suspend(struct pnp_dev *pdev, pm_message_t state) ++{ ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable all interrupts */ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return 0; ++} ++ ++static int ite_resume(struct pnp_dev *pdev) ++{ ++ int ret = 0; ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ if (dev->transmitting) { ++ /* wake up the transmitter */ ++ wake_up_interruptible(&dev->tx_queue); ++ } else { ++ /* enable the receiver */ ++ dev->params.enable_rx(dev); ++ } ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ return ret; ++} ++ ++static void ite_shutdown(struct pnp_dev *pdev) ++{ ++ struct ite_dev *dev = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ ite_dbg("%s called", __func__); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ /* disable all interrupts */ ++ dev->params.disable(dev); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++static struct pnp_driver ite_driver = { ++ .name = ITE_DRIVER_NAME, ++ .id_table = ite_ids, ++ .probe = ite_probe, ++ .remove = __devexit_p(ite_remove), ++ .suspend = ite_suspend, ++ .resume = ite_resume, ++ .shutdown = ite_shutdown, ++}; ++ ++int ite_init(void) ++{ ++ return pnp_register_driver(&ite_driver); ++} ++ ++void ite_exit(void) ++{ ++ pnp_unregister_driver(&ite_driver); ++} ++ ++MODULE_DEVICE_TABLE(pnp, ite_ids); ++MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver"); ++ ++MODULE_AUTHOR("Juan J. Garcia de Soria "); ++MODULE_LICENSE("GPL"); ++ ++module_init(ite_init); ++module_exit(ite_exit); +diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h +new file mode 100644 +index 0000000..16a19f5 +--- /dev/null ++++ b/drivers/media/rc/ite-cir.h +@@ -0,0 +1,481 @@ ++/* ++ * Driver for ITE Tech Inc. IT8712F/IT8512F CIR ++ * ++ * Copyright (C) 2010 Juan Jesús García de Soria ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA. ++ */ ++ ++/* platform driver name to register */ ++#define ITE_DRIVER_NAME "ite-cir" ++ ++/* logging macros */ ++#define ite_pr(level, text, ...) \ ++ printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) ++#define ite_dbg(text, ...) do { \ ++ if (debug) \ ++ printk(KERN_DEBUG \ ++ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \ ++} while (0) ++ ++#define ite_dbg_verbose(text, ...) do {\ ++ if (debug > 1) \ ++ printk(KERN_DEBUG \ ++ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \ ++} while (0) ++ ++/* FIFO sizes */ ++#define ITE_TX_FIFO_LEN 32 ++#define ITE_RX_FIFO_LEN 32 ++ ++/* interrupt types */ ++#define ITE_IRQ_TX_FIFO 1 ++#define ITE_IRQ_RX_FIFO 2 ++#define ITE_IRQ_RX_FIFO_OVERRUN 4 ++ ++/* forward declaration */ ++struct ite_dev; ++ ++/* struct for storing the parameters of different recognized devices */ ++struct ite_dev_params { ++ /* model of the device */ ++ const char *model; ++ ++ /* size of the I/O region */ ++ int io_region_size; ++ ++ /* true if the hardware supports transmission */ ++ bool hw_tx_capable; ++ ++ /* base sampling period, in ns */ ++ u32 sample_period; ++ ++ /* rx low carrier frequency, in Hz, 0 means no demodulation */ ++ unsigned int rx_low_carrier_freq; ++ ++ /* tx high carrier frequency, in Hz, 0 means no demodulation */ ++ unsigned int rx_high_carrier_freq; ++ ++ /* tx carrier frequency, in Hz */ ++ unsigned int tx_carrier_freq; ++ ++ /* duty cycle, 0-100 */ ++ int tx_duty_cycle; ++ ++ /* hw-specific operation function pointers; most of these must be ++ * called while holding the spin lock, except for the TX FIFO length ++ * one */ ++ /* get pending interrupt causes */ ++ int (*get_irq_causes) (struct ite_dev *dev); ++ ++ /* enable rx */ ++ void (*enable_rx) (struct ite_dev *dev); ++ ++ /* make rx enter the idle state; keep listening for a pulse, but stop ++ * streaming space bytes */ ++ void (*idle_rx) (struct ite_dev *dev); ++ ++ /* disable rx completely */ ++ void (*disable_rx) (struct ite_dev *dev); ++ ++ /* read bytes from RX FIFO; return read count */ ++ int (*get_rx_bytes) (struct ite_dev *dev, u8 *buf, int buf_size); ++ ++ /* enable tx FIFO space available interrupt */ ++ void (*enable_tx_interrupt) (struct ite_dev *dev); ++ ++ /* disable tx FIFO space available interrupt */ ++ void (*disable_tx_interrupt) (struct ite_dev *dev); ++ ++ /* get number of full TX FIFO slots */ ++ int (*get_tx_used_slots) (struct ite_dev *dev); ++ ++ /* put a byte to the TX FIFO */ ++ void (*put_tx_byte) (struct ite_dev *dev, u8 value); ++ ++ /* disable hardware completely */ ++ void (*disable) (struct ite_dev *dev); ++ ++ /* initialize the hardware */ ++ void (*init_hardware) (struct ite_dev *dev); ++ ++ /* set the carrier parameters */ ++ void (*set_carrier_params) (struct ite_dev *dev, bool high_freq, ++ bool use_demodulator, u8 carrier_freq_bits, ++ u8 allowance_bits, u8 pulse_width_bits); ++}; ++ ++/* ITE CIR device structure */ ++struct ite_dev { ++ struct pnp_dev *pdev; ++ struct rc_dev *rdev; ++ struct ir_raw_event rawir; ++ ++ /* sync data */ ++ spinlock_t lock; ++ bool in_use, transmitting; ++ ++ /* transmit support */ ++ int tx_fifo_allowance; ++ wait_queue_head_t tx_queue, tx_ended; ++ ++ /* hardware I/O settings */ ++ unsigned long cir_addr; ++ int cir_irq; ++ ++ /* overridable copy of model parameters */ ++ struct ite_dev_params params; ++}; ++ ++/* common values for all kinds of hardware */ ++ ++/* baud rate divisor default */ ++#define ITE_BAUDRATE_DIVISOR 1 ++ ++/* low-speed carrier frequency limits (Hz) */ ++#define ITE_LCF_MIN_CARRIER_FREQ 27000 ++#define ITE_LCF_MAX_CARRIER_FREQ 58000 ++ ++/* high-speed carrier frequency limits (Hz) */ ++#define ITE_HCF_MIN_CARRIER_FREQ 400000 ++#define ITE_HCF_MAX_CARRIER_FREQ 500000 ++ ++/* default carrier freq for when demodulator is off (Hz) */ ++#define ITE_DEFAULT_CARRIER_FREQ 38000 ++ ++/* default idling timeout in ns (0.2 seconds) */ ++#define ITE_IDLE_TIMEOUT 200000000UL ++ ++/* limit timeout values */ ++#define ITE_MIN_IDLE_TIMEOUT 100000000UL ++#define ITE_MAX_IDLE_TIMEOUT 1000000000UL ++ ++/* convert bits to us */ ++#define ITE_BITS_TO_NS(bits, sample_period) \ ++((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period)) ++ ++/* ++ * n in RDCR produces a tolerance of +/- n * 6.25% around the center ++ * carrier frequency... ++ * ++ * From two limit frequencies, L (low) and H (high), we can get both the ++ * center frequency F = (L + H) / 2 and the variation from the center ++ * frequency A = (H - L) / (H + L). We can use this in order to honor the ++ * s_rx_carrier_range() call in ir-core. We'll suppose that any request ++ * setting L=0 means we must shut down the demodulator. ++ */ ++#define ITE_RXDCR_PER_10000_STEP 625 ++ ++/* high speed carrier freq values */ ++#define ITE_CFQ_400 0x03 ++#define ITE_CFQ_450 0x08 ++#define ITE_CFQ_480 0x0b ++#define ITE_CFQ_500 0x0d ++ ++/* values for pulse widths */ ++#define ITE_TXMPW_A 0x02 ++#define ITE_TXMPW_B 0x03 ++#define ITE_TXMPW_C 0x04 ++#define ITE_TXMPW_D 0x05 ++#define ITE_TXMPW_E 0x06 ++ ++/* values for demodulator carrier range allowance */ ++#define ITE_RXDCR_DEFAULT 0x01 /* default carrier range */ ++#define ITE_RXDCR_MAX 0x07 /* default carrier range */ ++ ++/* DR TX bits */ ++#define ITE_TX_PULSE 0x00 ++#define ITE_TX_SPACE 0x80 ++#define ITE_TX_MAX_RLE 0x80 ++#define ITE_TX_RLE_MASK 0x7f ++ ++/* ++ * IT8712F ++ * ++ * hardware data obtained from: ++ * ++ * IT8712F ++ * Environment Control – Low Pin Count Input / Output ++ * (EC - LPC I/O) ++ * Preliminary Specification V0. 81 ++ */ ++ ++/* register offsets */ ++#define IT87_DR 0x00 /* data register */ ++#define IT87_IER 0x01 /* interrupt enable register */ ++#define IT87_RCR 0x02 /* receiver control register */ ++#define IT87_TCR1 0x03 /* transmitter control register 1 */ ++#define IT87_TCR2 0x04 /* transmitter control register 2 */ ++#define IT87_TSR 0x05 /* transmitter status register */ ++#define IT87_RSR 0x06 /* receiver status register */ ++#define IT87_BDLR 0x05 /* baud rate divisor low byte register */ ++#define IT87_BDHR 0x06 /* baud rate divisor high byte register */ ++#define IT87_IIR 0x07 /* interrupt identification register */ ++ ++#define IT87_IOREG_LENGTH 0x08 /* length of register file */ ++ ++/* IER bits */ ++#define IT87_TLDLIE 0x01 /* transmitter low data interrupt enable */ ++#define IT87_RDAIE 0x02 /* receiver data available interrupt enable */ ++#define IT87_RFOIE 0x04 /* receiver FIFO overrun interrupt enable */ ++#define IT87_IEC 0x08 /* interrupt enable control */ ++#define IT87_BR 0x10 /* baud rate register enable */ ++#define IT87_RESET 0x20 /* reset */ ++ ++/* RCR bits */ ++#define IT87_RXDCR 0x07 /* receiver demodulation carrier range mask */ ++#define IT87_RXACT 0x08 /* receiver active */ ++#define IT87_RXEND 0x10 /* receiver demodulation enable */ ++#define IT87_RXEN 0x20 /* receiver enable */ ++#define IT87_HCFS 0x40 /* high-speed carrier frequency select */ ++#define IT87_RDWOS 0x80 /* receiver data without sync */ ++ ++/* TCR1 bits */ ++#define IT87_TXMPM 0x03 /* transmitter modulation pulse mode mask */ ++#define IT87_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */ ++#define IT87_TXENDF 0x04 /* transmitter deferral */ ++#define IT87_TXRLE 0x08 /* transmitter run length enable */ ++#define IT87_FIFOTL 0x30 /* FIFO level threshold mask */ ++#define IT87_FIFOTL_DEFAULT 0x20 /* FIFO level threshold default ++ * 0x00 -> 1, 0x10 -> 7, 0x20 -> 17, ++ * 0x30 -> 25 */ ++#define IT87_ILE 0x40 /* internal loopback enable */ ++#define IT87_FIFOCLR 0x80 /* FIFO clear bit */ ++ ++/* TCR2 bits */ ++#define IT87_TXMPW 0x07 /* transmitter modulation pulse width mask */ ++#define IT87_TXMPW_DEFAULT 0x04 /* default modulation pulse width */ ++#define IT87_CFQ 0xf8 /* carrier frequency mask */ ++#define IT87_CFQ_SHIFT 3 /* carrier frequency bit shift */ ++ ++/* TSR bits */ ++#define IT87_TXFBC 0x3f /* transmitter FIFO byte count mask */ ++ ++/* RSR bits */ ++#define IT87_RXFBC 0x3f /* receiver FIFO byte count mask */ ++#define IT87_RXFTO 0x80 /* receiver FIFO time-out */ ++ ++/* IIR bits */ ++#define IT87_IP 0x01 /* interrupt pending */ ++#define IT87_II 0x06 /* interrupt identification mask */ ++#define IT87_II_NOINT 0x00 /* no interrupt */ ++#define IT87_II_TXLDL 0x02 /* transmitter low data level */ ++#define IT87_II_RXDS 0x04 /* receiver data stored */ ++#define IT87_II_RXFO 0x06 /* receiver FIFO overrun */ ++ ++/* ++ * IT8512E/F ++ * ++ * Hardware data obtained from: ++ * ++ * IT8512E/F ++ * Embedded Controller ++ * Preliminary Specification V0.4.1 ++ * ++ * Note that the CIR registers are not directly available to the host, because ++ * they only are accessible to the integrated microcontroller. Thus, in order ++ * use it, some kind of bridging is required. As the bridging may depend on ++ * the controller firmware in use, we are going to use the PNP ID in order to ++ * determine the strategy and ports available. See after these generic ++ * IT8512E/F register definitions for register definitions for those ++ * strategies. ++ */ ++ ++/* register offsets */ ++#define IT85_C0DR 0x00 /* data register */ ++#define IT85_C0MSTCR 0x01 /* master control register */ ++#define IT85_C0IER 0x02 /* interrupt enable register */ ++#define IT85_C0IIR 0x03 /* interrupt identification register */ ++#define IT85_C0CFR 0x04 /* carrier frequency register */ ++#define IT85_C0RCR 0x05 /* receiver control register */ ++#define IT85_C0TCR 0x06 /* transmitter control register */ ++#define IT85_C0SCK 0x07 /* slow clock control register */ ++#define IT85_C0BDLR 0x08 /* baud rate divisor low byte register */ ++#define IT85_C0BDHR 0x09 /* baud rate divisor high byte register */ ++#define IT85_C0TFSR 0x0a /* transmitter FIFO status register */ ++#define IT85_C0RFSR 0x0b /* receiver FIFO status register */ ++#define IT85_C0WCL 0x0d /* wakeup code length register */ ++#define IT85_C0WCR 0x0e /* wakeup code read/write register */ ++#define IT85_C0WPS 0x0f /* wakeup power control/status register */ ++ ++#define IT85_IOREG_LENGTH 0x10 /* length of register file */ ++ ++/* C0MSTCR bits */ ++#define IT85_RESET 0x01 /* reset */ ++#define IT85_FIFOCLR 0x02 /* FIFO clear bit */ ++#define IT85_FIFOTL 0x0c /* FIFO level threshold mask */ ++#define IT85_FIFOTL_DEFAULT 0x08 /* FIFO level threshold default ++ * 0x00 -> 1, 0x04 -> 7, 0x08 -> 17, ++ * 0x0c -> 25 */ ++#define IT85_ILE 0x10 /* internal loopback enable */ ++#define IT85_ILSEL 0x20 /* internal loopback select */ ++ ++/* C0IER bits */ ++#define IT85_TLDLIE 0x01 /* TX low data level interrupt enable */ ++#define IT85_RDAIE 0x02 /* RX data available interrupt enable */ ++#define IT85_RFOIE 0x04 /* RX FIFO overrun interrupt enable */ ++#define IT85_IEC 0x80 /* interrupt enable function control */ ++ ++/* C0IIR bits */ ++#define IT85_TLDLI 0x01 /* transmitter low data level interrupt */ ++#define IT85_RDAI 0x02 /* receiver data available interrupt */ ++#define IT85_RFOI 0x04 /* receiver FIFO overrun interrupt */ ++#define IT85_NIP 0x80 /* no interrupt pending */ ++ ++/* C0CFR bits */ ++#define IT85_CFQ 0x1f /* carrier frequency mask */ ++#define IT85_HCFS 0x20 /* high speed carrier frequency select */ ++ ++/* C0RCR bits */ ++#define IT85_RXDCR 0x07 /* receiver demodulation carrier range mask */ ++#define IT85_RXACT 0x08 /* receiver active */ ++#define IT85_RXEND 0x10 /* receiver demodulation enable */ ++#define IT85_RDWOS 0x20 /* receiver data without sync */ ++#define IT85_RXEN 0x80 /* receiver enable */ ++ ++/* C0TCR bits */ ++#define IT85_TXMPW 0x07 /* transmitter modulation pulse width mask */ ++#define IT85_TXMPW_DEFAULT 0x04 /* default modulation pulse width */ ++#define IT85_TXMPM 0x18 /* transmitter modulation pulse mode mask */ ++#define IT85_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */ ++#define IT85_TXENDF 0x20 /* transmitter deferral */ ++#define IT85_TXRLE 0x40 /* transmitter run length enable */ ++ ++/* C0SCK bits */ ++#define IT85_SCKS 0x01 /* slow clock select */ ++#define IT85_TXDCKG 0x02 /* TXD clock gating */ ++#define IT85_DLL1P8E 0x04 /* DLL 1.8432M enable */ ++#define IT85_DLLTE 0x08 /* DLL test enable */ ++#define IT85_BRCM 0x70 /* baud rate count mode */ ++#define IT85_DLLOCK 0x80 /* DLL lock */ ++ ++/* C0TFSR bits */ ++#define IT85_TXFBC 0x3f /* transmitter FIFO count mask */ ++ ++/* C0RFSR bits */ ++#define IT85_RXFBC 0x3f /* receiver FIFO count mask */ ++#define IT85_RXFTO 0x80 /* receiver FIFO time-out */ ++ ++/* C0WCL bits */ ++#define IT85_WCL 0x3f /* wakeup code length mask */ ++ ++/* C0WPS bits */ ++#define IT85_CIRPOSIE 0x01 /* power on/off status interrupt enable */ ++#define IT85_CIRPOIS 0x02 /* power on/off interrupt status */ ++#define IT85_CIRPOII 0x04 /* power on/off interrupt identification */ ++#define IT85_RCRST 0x10 /* wakeup code reading counter reset bit */ ++#define IT85_WCRST 0x20 /* wakeup code writing counter reset bit */ ++ ++/* ++ * ITE8708 ++ * ++ * Hardware data obtained from hacked driver for IT8512 in this forum post: ++ * ++ * http://ubuntuforums.org/showthread.php?t=1028640 ++ * ++ * Although there's no official documentation for that driver, analysis would ++ * suggest that it maps the 16 registers of IT8512 onto two 8-register banks, ++ * selectable by a single bank-select bit that's mapped onto both banks. The ++ * IT8512 registers are mapped in a different order, so that the first bank ++ * maps the ones that are used more often, and two registers that share a ++ * reserved high-order bit are placed at the same offset in both banks in ++ * order to reuse the reserved bit as the bank select bit. ++ */ ++ ++/* register offsets */ ++ ++/* mapped onto both banks */ ++#define IT8708_BANKSEL 0x07 /* bank select register */ ++#define IT8708_HRAE 0x80 /* high registers access enable */ ++ ++/* mapped onto the low bank */ ++#define IT8708_C0DR 0x00 /* data register */ ++#define IT8708_C0MSTCR 0x01 /* master control register */ ++#define IT8708_C0IER 0x02 /* interrupt enable register */ ++#define IT8708_C0IIR 0x03 /* interrupt identification register */ ++#define IT8708_C0RFSR 0x04 /* receiver FIFO status register */ ++#define IT8708_C0RCR 0x05 /* receiver control register */ ++#define IT8708_C0TFSR 0x06 /* transmitter FIFO status register */ ++#define IT8708_C0TCR 0x07 /* transmitter control register */ ++ ++/* mapped onto the high bank */ ++#define IT8708_C0BDLR 0x01 /* baud rate divisor low byte register */ ++#define IT8708_C0BDHR 0x02 /* baud rate divisor high byte register */ ++#define IT8708_C0CFR 0x04 /* carrier frequency register */ ++ ++/* registers whose bank mapping we don't know, since they weren't being used ++ * in the hacked driver... most probably they belong to the high bank too, ++ * since they fit in the holes the other registers leave */ ++#define IT8708_C0SCK 0x03 /* slow clock control register */ ++#define IT8708_C0WCL 0x05 /* wakeup code length register */ ++#define IT8708_C0WCR 0x06 /* wakeup code read/write register */ ++#define IT8708_C0WPS 0x07 /* wakeup power control/status register */ ++ ++#define IT8708_IOREG_LENGTH 0x08 /* length of register file */ ++ ++/* two more registers that are defined in the hacked driver, but can't be ++ * found in the data sheets; no idea what they are or how they are accessed, ++ * since the hacked driver doesn't seem to use them */ ++#define IT8708_CSCRR 0x00 ++#define IT8708_CGPINTR 0x01 ++ ++/* CSCRR bits */ ++#define IT8708_CSCRR_SCRB 0x3f ++#define IT8708_CSCRR_PM 0x80 ++ ++/* CGPINTR bits */ ++#define IT8708_CGPINT 0x01 ++ ++/* ++ * ITE8709 ++ * ++ * Hardware interfacing data obtained from the original lirc_ite8709 driver. ++ * Verbatim from its sources: ++ * ++ * The ITE8709 device seems to be the combination of IT8512 superIO chip and ++ * a specific firmware running on the IT8512's embedded micro-controller. ++ * In addition of the embedded micro-controller, the IT8512 chip contains a ++ * CIR module and several other modules. A few modules are directly accessible ++ * by the host CPU, but most of them are only accessible by the ++ * micro-controller. The CIR module is only accessible by the ++ * micro-controller. ++ * ++ * The battery-backed SRAM module is accessible by the host CPU and the ++ * micro-controller. So one of the MC's firmware role is to act as a bridge ++ * between the host CPU and the CIR module. The firmware implements a kind of ++ * communication protocol using the SRAM module as a shared memory. The IT8512 ++ * specification is publicly available on ITE's web site, but the ++ * communication protocol is not, so it was reverse-engineered. ++ */ ++ ++/* register offsets */ ++#define IT8709_RAM_IDX 0x00 /* index into the SRAM module bytes */ ++#define IT8709_RAM_VAL 0x01 /* read/write data to the indexed byte */ ++ ++#define IT8709_IOREG_LENGTH 0x02 /* length of register file */ ++ ++/* register offsets inside the SRAM module */ ++#define IT8709_MODE 0x1a /* request/ack byte */ ++#define IT8709_REG_IDX 0x1b /* index of the CIR register to access */ ++#define IT8709_REG_VAL 0x1c /* value read/to be written */ ++#define IT8709_IIR 0x1e /* interrupt identification register */ ++#define IT8709_RFSR 0x1f /* receiver FIFO status register */ ++#define IT8709_FIFO 0x20 /* start of in RAM RX FIFO copy */ ++ ++/* MODE values */ ++#define IT8709_IDLE 0x00 ++#define IT8709_WRITE 0x01 ++#define IT8709_READ 0x02 +diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile +index cb72121..85cac7d 100644 +--- a/drivers/media/rc/keymaps/Makefile ++++ b/drivers/media/rc/keymaps/Makefile +@@ -37,7 +37,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ + rc-gadmei-rm008z.o \ + rc-genius-tvgo-a11mce.o \ + rc-gotview7135.o \ +- rc-hauppauge-new.o \ + rc-imon-mce.o \ + rc-imon-pad.o \ + rc-iodata-bctv7e.o \ +@@ -68,8 +67,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ + rc-proteus-2309.o \ + rc-purpletv.o \ + rc-pv951.o \ +- rc-rc5-hauppauge-new.o \ +- rc-rc5-tv.o \ ++ rc-hauppauge.o \ + rc-rc6-mce.o \ + rc-real-audio-220-32-keys.o \ + rc-streamzap.o \ +diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c +index 136d395..9a8752f 100644 +--- a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c ++++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c +@@ -50,9 +50,9 @@ static struct rc_map_table adstech_dvb_t_pci[] = { + { 0x13, KEY_TUNER }, /* Live */ + { 0x0a, KEY_A }, + { 0x12, KEY_B }, +- { 0x03, KEY_PROG1 }, /* 1 */ +- { 0x01, KEY_PROG2 }, /* 2 */ +- { 0x00, KEY_PROG3 }, /* 3 */ ++ { 0x03, KEY_RED }, /* 1 */ ++ { 0x01, KEY_GREEN }, /* 2 */ ++ { 0x00, KEY_YELLOW }, /* 3 */ + { 0x06, KEY_DVD }, + { 0x48, KEY_AUX }, /* Photo */ + { 0x40, KEY_VIDEO }, +diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c +index 3ddb41b..c25809d 100644 +--- a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c ++++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c +@@ -26,12 +26,12 @@ static struct rc_map_table avermedia_dvbt[] = { + { 0x16, KEY_8 }, /* '8' / 'down arrow' */ + { 0x36, KEY_9 }, /* '9' */ + +- { 0x20, KEY_LIST }, /* 'source' */ ++ { 0x20, KEY_VIDEO }, /* 'source' */ + { 0x10, KEY_TEXT }, /* 'teletext' */ + { 0x00, KEY_POWER }, /* 'power' */ + { 0x04, KEY_AUDIO }, /* 'audio' */ + { 0x06, KEY_ZOOM }, /* 'full screen' */ +- { 0x18, KEY_VIDEO }, /* 'display' */ ++ { 0x18, KEY_SWITCHVIDEOMODE }, /* 'display' */ + { 0x38, KEY_SEARCH }, /* 'loop' */ + { 0x08, KEY_INFO }, /* 'preview' */ + { 0x2a, KEY_REWIND }, /* 'backward <<' */ +diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c +index 357fea5..3d2cbe4 100644 +--- a/drivers/media/rc/keymaps/rc-avermedia-m135a.c ++++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c +@@ -108,7 +108,7 @@ static struct rc_map_table avermedia_m135a[] = { + { 0x0414, KEY_TEXT }, + { 0x0415, KEY_EPG }, + { 0x041a, KEY_TV2 }, /* PIP */ +- { 0x041b, KEY_MHP }, /* Snapshot */ ++ { 0x041b, KEY_CAMERA }, /* Snapshot */ + + { 0x0417, KEY_RECORD }, + { 0x0416, KEY_PLAYPAUSE }, +diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c +index e694e6e..8cd7f28 100644 +--- a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c ++++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c +@@ -56,7 +56,7 @@ static struct rc_map_table avermedia_m733a_rm_k6[] = { + { 0x0414, KEY_TEXT }, + { 0x0415, KEY_EPG }, + { 0x041a, KEY_TV2 }, /* PIP */ +- { 0x041b, KEY_MHP }, /* Snapshot */ ++ { 0x041b, KEY_CAMERA }, /* Snapshot */ + + { 0x0417, KEY_RECORD }, + { 0x0416, KEY_PLAYPAUSE }, +diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c +index f4ca1ff..9d68af2 100644 +--- a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c ++++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c +@@ -31,7 +31,7 @@ static struct rc_map_table avermedia_rm_ks[] = { + { 0x0505, KEY_VOLUMEDOWN }, + { 0x0506, KEY_MUTE }, + { 0x0507, KEY_RIGHT }, +- { 0x0508, KEY_PROG1 }, ++ { 0x0508, KEY_RED }, + { 0x0509, KEY_1 }, + { 0x050a, KEY_2 }, + { 0x050b, KEY_3 }, +diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c +index 4b787fa..8bf058f 100644 +--- a/drivers/media/rc/keymaps/rc-behold-columbus.c ++++ b/drivers/media/rc/keymaps/rc-behold-columbus.c +@@ -28,7 +28,7 @@ static struct rc_map_table behold_columbus[] = { + * */ + + { 0x13, KEY_MUTE }, +- { 0x11, KEY_PROPS }, ++ { 0x11, KEY_VIDEO }, + { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ + { 0x12, KEY_POWER }, + +diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c +index 0ee1f14..c909a23 100644 +--- a/drivers/media/rc/keymaps/rc-behold.c ++++ b/drivers/media/rc/keymaps/rc-behold.c +@@ -97,7 +97,7 @@ static struct rc_map_table behold[] = { + { 0x6b861a, KEY_STOP }, + { 0x6b860e, KEY_TEXT }, + { 0x6b861f, KEY_RED }, /*XXX KEY_AUDIO */ +- { 0x6b861e, KEY_YELLOW }, /*XXX KEY_SOURCE */ ++ { 0x6b861e, KEY_VIDEO }, + + /* 0x1d 0x13 0x19 * + * SLEEP PREVIEW DVB * +diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c +index 97fc386..2f66e43 100644 +--- a/drivers/media/rc/keymaps/rc-budget-ci-old.c ++++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c +@@ -12,7 +12,8 @@ + + #include + +-/* From reading the following remotes: ++/* ++ * From reading the following remotes: + * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 + * Hauppauge (from NOVA-CI-s box product) + * This is a "middle of the road" approach, differences are noted +diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c +index 99520ff..cf3a6bf 100644 +--- a/drivers/media/rc/keymaps/rc-cinergy.c ++++ b/drivers/media/rc/keymaps/rc-cinergy.c +@@ -25,7 +25,7 @@ static struct rc_map_table cinergy[] = { + { 0x09, KEY_9 }, + + { 0x0a, KEY_POWER }, +- { 0x0b, KEY_PROG1 }, /* app */ ++ { 0x0b, KEY_MEDIA }, /* app */ + { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ + { 0x0d, KEY_CHANNELUP }, /* channel */ + { 0x0e, KEY_CHANNELDOWN }, /* channel- */ +diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c +index 43912bd..82c0200 100644 +--- a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c ++++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c +@@ -32,7 +32,7 @@ static struct rc_map_table dntv_live_dvb_t[] = { + { 0x0c, KEY_SEARCH }, /* scan */ + { 0x0d, KEY_STOP }, + { 0x0e, KEY_PAUSE }, +- { 0x0f, KEY_LIST }, /* source */ ++ { 0x0f, KEY_VIDEO }, /* source */ + + { 0x10, KEY_MUTE }, + { 0x11, KEY_REWIND }, /* backward << */ +diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c +index afa4e92..e56ac6e 100644 +--- a/drivers/media/rc/keymaps/rc-encore-enltv.c ++++ b/drivers/media/rc/keymaps/rc-encore-enltv.c +@@ -24,7 +24,7 @@ static struct rc_map_table encore_enltv[] = { + { 0x1e, KEY_TV }, + { 0x00, KEY_VIDEO }, + { 0x01, KEY_AUDIO }, /* music */ +- { 0x02, KEY_MHP }, /* picture */ ++ { 0x02, KEY_CAMERA }, /* picture */ + + { 0x1f, KEY_1 }, + { 0x03, KEY_2 }, +@@ -77,7 +77,7 @@ static struct rc_map_table encore_enltv[] = { + { 0x50, KEY_SLEEP }, /* shutdown */ + { 0x51, KEY_MODE }, /* stereo > main */ + { 0x52, KEY_SELECT }, /* stereo > sap */ +- { 0x53, KEY_PROG1 }, /* teletext */ ++ { 0x53, KEY_TEXT }, /* teletext */ + + + { 0x59, KEY_RED }, /* AP1 */ +diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c +index 7d5b00e..b6264f1 100644 +--- a/drivers/media/rc/keymaps/rc-encore-enltv2.c ++++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c +@@ -32,7 +32,7 @@ static struct rc_map_table encore_enltv2[] = { + { 0x64, KEY_LAST }, /* +100 */ + { 0x4e, KEY_AGAIN }, /* Recall */ + +- { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ ++ { 0x6c, KEY_VIDEO }, /* Video Source */ + { 0x5e, KEY_MENU }, + { 0x56, KEY_SCREEN }, + { 0x7a, KEY_SETUP }, +diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c +index aea2f4a..a8b0f66 100644 +--- a/drivers/media/rc/keymaps/rc-flydvb.c ++++ b/drivers/media/rc/keymaps/rc-flydvb.c +@@ -37,8 +37,8 @@ static struct rc_map_table flydvb[] = { + { 0x13, KEY_CHANNELDOWN }, /* CH- */ + { 0x1d, KEY_ENTER }, /* Enter */ + +- { 0x1a, KEY_MODE }, /* PIP */ +- { 0x18, KEY_TUNER }, /* Source */ ++ { 0x1a, KEY_TV2 }, /* PIP */ ++ { 0x18, KEY_VIDEO }, /* Source */ + + { 0x1e, KEY_RECORD }, /* Record/Pause */ + { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ +diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c +deleted file mode 100644 +index bd11da4..0000000 +--- a/drivers/media/rc/keymaps/rc-hauppauge-new.c ++++ /dev/null +@@ -1,100 +0,0 @@ +-/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller +- * +- * keymap imported from ir-keymaps.c +- * +- * Copyright (c) 2010 by Mauro Carvalho Chehab +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- */ +- +-#include +- +-/* Hauppauge: the newer, gray remotes (seems there are multiple +- * slightly different versions), shipped with cx88+ivtv cards. +- * almost rc5 coding, but some non-standard keys */ +- +-static struct rc_map_table hauppauge_new[] = { +- /* Keys 0 to 9 */ +- { 0x00, KEY_0 }, +- { 0x01, KEY_1 }, +- { 0x02, KEY_2 }, +- { 0x03, KEY_3 }, +- { 0x04, KEY_4 }, +- { 0x05, KEY_5 }, +- { 0x06, KEY_6 }, +- { 0x07, KEY_7 }, +- { 0x08, KEY_8 }, +- { 0x09, KEY_9 }, +- +- { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ +- { 0x0b, KEY_RED }, /* red button */ +- { 0x0c, KEY_RADIO }, +- { 0x0d, KEY_MENU }, +- { 0x0e, KEY_SUBTITLE }, /* also the # key */ +- { 0x0f, KEY_MUTE }, +- { 0x10, KEY_VOLUMEUP }, +- { 0x11, KEY_VOLUMEDOWN }, +- { 0x12, KEY_PREVIOUS }, /* previous channel */ +- { 0x14, KEY_UP }, +- { 0x15, KEY_DOWN }, +- { 0x16, KEY_LEFT }, +- { 0x17, KEY_RIGHT }, +- { 0x18, KEY_VIDEO }, /* Videos */ +- { 0x19, KEY_AUDIO }, /* Music */ +- /* 0x1a: Pictures - presume this means +- "Multimedia Home Platform" - +- no "PICTURES" key in input.h +- */ +- { 0x1a, KEY_MHP }, +- +- { 0x1b, KEY_EPG }, /* Guide */ +- { 0x1c, KEY_TV }, +- { 0x1e, KEY_NEXTSONG }, /* skip >| */ +- { 0x1f, KEY_EXIT }, /* back/exit */ +- { 0x20, KEY_CHANNELUP }, /* channel / program + */ +- { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ +- { 0x22, KEY_CHANNEL }, /* source (old black remote) */ +- { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ +- { 0x25, KEY_ENTER }, /* OK */ +- { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ +- { 0x29, KEY_BLUE }, /* blue key */ +- { 0x2e, KEY_GREEN }, /* green button */ +- { 0x30, KEY_PAUSE }, /* pause */ +- { 0x32, KEY_REWIND }, /* backward << */ +- { 0x34, KEY_FASTFORWARD }, /* forward >> */ +- { 0x35, KEY_PLAY }, +- { 0x36, KEY_STOP }, +- { 0x37, KEY_RECORD }, /* recording */ +- { 0x38, KEY_YELLOW }, /* yellow key */ +- { 0x3b, KEY_SELECT }, /* top right button */ +- { 0x3c, KEY_ZOOM }, /* full */ +- { 0x3d, KEY_POWER }, /* system power (green button) */ +-}; +- +-static struct rc_map_list hauppauge_new_map = { +- .map = { +- .scan = hauppauge_new, +- .size = ARRAY_SIZE(hauppauge_new), +- .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ +- .name = RC_MAP_HAUPPAUGE_NEW, +- } +-}; +- +-static int __init init_rc_map_hauppauge_new(void) +-{ +- return rc_map_register(&hauppauge_new_map); +-} +- +-static void __exit exit_rc_map_hauppauge_new(void) +-{ +- rc_map_unregister(&hauppauge_new_map); +-} +- +-module_init(init_rc_map_hauppauge_new) +-module_exit(exit_rc_map_hauppauge_new) +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Mauro Carvalho Chehab "); +diff --git a/drivers/media/rc/keymaps/rc-hauppauge.c b/drivers/media/rc/keymaps/rc-hauppauge.c +new file mode 100644 +index 0000000..cd3db77 +--- /dev/null ++++ b/drivers/media/rc/keymaps/rc-hauppauge.c +@@ -0,0 +1,241 @@ ++/* rc-hauppauge.c - Keytable for Hauppauge Remote Controllers ++ * ++ * keymap imported from ir-keymaps.c ++ * ++ * This map currently contains the code for four different RCs: ++ * - New Hauppauge Gray; ++ * - Old Hauppauge Gray (with a golden screen for media keys); ++ * - Hauppauge Black; ++ * - DSR-0112 remote bundled with Haupauge MiniStick. ++ * ++ * Copyright (c) 2010-2011 by Mauro Carvalho Chehab ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++ ++/* ++ * Hauppauge:the newer, gray remotes (seems there are multiple ++ * slightly different versions), shipped with cx88+ivtv cards. ++ * ++ * This table contains the complete RC5 code, instead of just the data part ++ */ ++ ++static struct rc_map_table rc5_hauppauge_new[] = { ++ /* ++ * Remote Controller Hauppauge Gray found on modern devices ++ * Keycodes start with address = 0x1e ++ */ ++ ++ { 0x1e3b, KEY_SELECT }, /* GO / house symbol */ ++ { 0x1e3d, KEY_POWER2 }, /* system power (green button) */ ++ ++ { 0x1e1c, KEY_TV }, ++ { 0x1e18, KEY_VIDEO }, /* Videos */ ++ { 0x1e19, KEY_AUDIO }, /* Music */ ++ { 0x1e1a, KEY_CAMERA }, /* Pictures */ ++ ++ { 0x1e1b, KEY_EPG }, /* Guide */ ++ { 0x1e0c, KEY_RADIO }, ++ ++ { 0x1e14, KEY_UP }, ++ { 0x1e15, KEY_DOWN }, ++ { 0x1e16, KEY_LEFT }, ++ { 0x1e17, KEY_RIGHT }, ++ { 0x1e25, KEY_OK }, /* OK */ ++ ++ { 0x1e1f, KEY_EXIT }, /* back/exit */ ++ { 0x1e0d, KEY_MENU }, ++ ++ { 0x1e10, KEY_VOLUMEUP }, ++ { 0x1e11, KEY_VOLUMEDOWN }, ++ ++ { 0x1e12, KEY_PREVIOUS }, /* previous channel */ ++ { 0x1e0f, KEY_MUTE }, ++ ++ { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ ++ { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ ++ ++ { 0x1e37, KEY_RECORD }, /* recording */ ++ { 0x1e36, KEY_STOP }, ++ ++ { 0x1e32, KEY_REWIND }, /* backward << */ ++ { 0x1e35, KEY_PLAY }, ++ { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ ++ ++ { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ ++ { 0x1e30, KEY_PAUSE }, /* pause */ ++ { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ ++ ++ { 0x1e01, KEY_1 }, ++ { 0x1e02, KEY_2 }, ++ { 0x1e03, KEY_3 }, ++ ++ { 0x1e04, KEY_4 }, ++ { 0x1e05, KEY_5 }, ++ { 0x1e06, KEY_6 }, ++ ++ { 0x1e07, KEY_7 }, ++ { 0x1e08, KEY_8 }, ++ { 0x1e09, KEY_9 }, ++ ++ { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ ++ { 0x1e00, KEY_0 }, ++ { 0x1e0e, KEY_SUBTITLE }, /* also the Pound key (#) */ ++ ++ { 0x1e0b, KEY_RED }, /* red button */ ++ { 0x1e2e, KEY_GREEN }, /* green button */ ++ { 0x1e38, KEY_YELLOW }, /* yellow key */ ++ { 0x1e29, KEY_BLUE }, /* blue key */ ++ ++ /* ++ * Old Remote Controller Hauppauge Gray with a golden screen ++ * Keycodes start with address = 0x1f ++ */ ++ { 0x1f3d, KEY_POWER2 }, /* system power (green button) */ ++ { 0x1f3b, KEY_SELECT }, /* GO */ ++ ++ /* Keys 0 to 9 */ ++ { 0x1f00, KEY_0 }, ++ { 0x1f01, KEY_1 }, ++ { 0x1f02, KEY_2 }, ++ { 0x1f03, KEY_3 }, ++ { 0x1f04, KEY_4 }, ++ { 0x1f05, KEY_5 }, ++ { 0x1f06, KEY_6 }, ++ { 0x1f07, KEY_7 }, ++ { 0x1f08, KEY_8 }, ++ { 0x1f09, KEY_9 }, ++ ++ { 0x1f1f, KEY_EXIT }, /* back/exit */ ++ { 0x1f0d, KEY_MENU }, ++ ++ { 0x1f10, KEY_VOLUMEUP }, ++ { 0x1f11, KEY_VOLUMEDOWN }, ++ { 0x1f20, KEY_CHANNELUP }, /* channel / program + */ ++ { 0x1f21, KEY_CHANNELDOWN }, /* channel / program - */ ++ { 0x1f25, KEY_ENTER }, /* OK */ ++ ++ { 0x1f0b, KEY_RED }, /* red button */ ++ { 0x1f2e, KEY_GREEN }, /* green button */ ++ { 0x1f38, KEY_YELLOW }, /* yellow key */ ++ { 0x1f29, KEY_BLUE }, /* blue key */ ++ ++ { 0x1f0f, KEY_MUTE }, ++ { 0x1f0c, KEY_RADIO }, /* There's no indicator on this key */ ++ { 0x1f3c, KEY_ZOOM }, /* full */ ++ ++ { 0x1f32, KEY_REWIND }, /* backward << */ ++ { 0x1f35, KEY_PLAY }, ++ { 0x1f34, KEY_FASTFORWARD }, /* forward >> */ ++ ++ { 0x1f37, KEY_RECORD }, /* recording */ ++ { 0x1f36, KEY_STOP }, ++ { 0x1f30, KEY_PAUSE }, /* pause */ ++ ++ { 0x1f24, KEY_PREVIOUSSONG }, /* replay |< */ ++ { 0x1f1e, KEY_NEXTSONG }, /* skip >| */ ++ ++ /* ++ * Keycodes for DSR-0112 remote bundled with Haupauge MiniStick ++ * Keycodes start with address = 0x1d ++ */ ++ { 0x1d00, KEY_0 }, ++ { 0x1d01, KEY_1 }, ++ { 0x1d02, KEY_2 }, ++ { 0x1d03, KEY_3 }, ++ { 0x1d04, KEY_4 }, ++ { 0x1d05, KEY_5 }, ++ { 0x1d06, KEY_6 }, ++ { 0x1d07, KEY_7 }, ++ { 0x1d08, KEY_8 }, ++ { 0x1d09, KEY_9 }, ++ { 0x1d0a, KEY_TEXT }, ++ { 0x1d0d, KEY_MENU }, ++ { 0x1d0f, KEY_MUTE }, ++ { 0x1d10, KEY_VOLUMEUP }, ++ { 0x1d11, KEY_VOLUMEDOWN }, ++ { 0x1d12, KEY_PREVIOUS }, /* Prev.Ch .. ??? */ ++ { 0x1d14, KEY_UP }, ++ { 0x1d15, KEY_DOWN }, ++ { 0x1d16, KEY_LEFT }, ++ { 0x1d17, KEY_RIGHT }, ++ { 0x1d1c, KEY_TV }, ++ { 0x1d1e, KEY_NEXT }, /* >| */ ++ { 0x1d1f, KEY_EXIT }, ++ { 0x1d20, KEY_CHANNELUP }, ++ { 0x1d21, KEY_CHANNELDOWN }, ++ { 0x1d24, KEY_LAST }, /* <| */ ++ { 0x1d25, KEY_OK }, ++ { 0x1d30, KEY_PAUSE }, ++ { 0x1d32, KEY_REWIND }, ++ { 0x1d34, KEY_FASTFORWARD }, ++ { 0x1d35, KEY_PLAY }, ++ { 0x1d36, KEY_STOP }, ++ { 0x1d37, KEY_RECORD }, ++ { 0x1d3b, KEY_GOTO }, ++ { 0x1d3d, KEY_POWER }, ++ { 0x1d3f, KEY_HOME }, ++ ++ /* ++ * Keycodes for the old Black Remote Controller ++ * This one also uses RC-5 protocol ++ * Keycodes start with address = 0x00 ++ */ ++ { 0x001f, KEY_TV }, ++ { 0x0020, KEY_CHANNELUP }, ++ { 0x000c, KEY_RADIO }, ++ ++ { 0x0011, KEY_VOLUMEDOWN }, ++ { 0x002e, KEY_ZOOM }, /* full screen */ ++ { 0x0010, KEY_VOLUMEUP }, ++ ++ { 0x000d, KEY_MUTE }, ++ { 0x0021, KEY_CHANNELDOWN }, ++ { 0x0022, KEY_VIDEO }, /* source */ ++ ++ { 0x0001, KEY_1 }, ++ { 0x0002, KEY_2 }, ++ { 0x0003, KEY_3 }, ++ ++ { 0x0004, KEY_4 }, ++ { 0x0005, KEY_5 }, ++ { 0x0006, KEY_6 }, ++ ++ { 0x0007, KEY_7 }, ++ { 0x0008, KEY_8 }, ++ { 0x0009, KEY_9 }, ++ ++ { 0x001e, KEY_RED }, /* Reserved */ ++ { 0x0000, KEY_0 }, ++ { 0x0026, KEY_SLEEP }, /* Minimize */ ++}; ++ ++static struct rc_map_list rc5_hauppauge_new_map = { ++ .map = { ++ .scan = rc5_hauppauge_new, ++ .size = ARRAY_SIZE(rc5_hauppauge_new), ++ .rc_type = RC_TYPE_RC5, ++ .name = RC_MAP_HAUPPAUGE, ++ } ++}; ++ ++static int __init init_rc_map_rc5_hauppauge_new(void) ++{ ++ return rc_map_register(&rc5_hauppauge_new_map); ++} ++ ++static void __exit exit_rc_map_rc5_hauppauge_new(void) ++{ ++ rc_map_unregister(&rc5_hauppauge_new_map); ++} ++ ++module_init(init_rc_map_rc5_hauppauge_new) ++module_exit(exit_rc_map_rc5_hauppauge_new) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Mauro Carvalho Chehab "); +diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c +index cb67184..937a819 100644 +--- a/drivers/media/rc/keymaps/rc-imon-mce.c ++++ b/drivers/media/rc/keymaps/rc-imon-mce.c +@@ -111,7 +111,7 @@ static struct rc_map_table imon_mce[] = { + { 0x800ff44d, KEY_TITLE }, + + { 0x800ff40c, KEY_POWER }, +- { 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */ ++ { 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */ + + }; + +diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c +index eef46b7..63d42bd 100644 +--- a/drivers/media/rc/keymaps/rc-imon-pad.c ++++ b/drivers/media/rc/keymaps/rc-imon-pad.c +@@ -125,7 +125,7 @@ static struct rc_map_table imon_pad[] = { + { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ + { 0x02000065, KEY_COMPOSE }, /* RightMenu */ + { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ +- { 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */ ++ { 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */ + { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ + }; + +diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c +index 3ce6ef7..7f33edb 100644 +--- a/drivers/media/rc/keymaps/rc-kworld-315u.c ++++ b/drivers/media/rc/keymaps/rc-kworld-315u.c +@@ -17,7 +17,7 @@ + + static struct rc_map_table kworld_315u[] = { + { 0x6143, KEY_POWER }, +- { 0x6101, KEY_TUNER }, /* source */ ++ { 0x6101, KEY_VIDEO }, /* source */ + { 0x610b, KEY_ZOOM }, + { 0x6103, KEY_POWER2 }, /* shutdown */ + +diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +index e45f0b8..08d1831 100644 +--- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c ++++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c +@@ -17,7 +17,7 @@ + */ + + static struct rc_map_table kworld_plus_tv_analog[] = { +- { 0x0c, KEY_PROG1 }, /* Kworld key */ ++ { 0x0c, KEY_LEFTMETA }, /* Kworld key */ + { 0x16, KEY_CLOSECD }, /* -> ) */ + { 0x1d, KEY_POWER2 }, + +diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c +index fa8fd0a..8e9969d 100644 +--- a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c ++++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c +@@ -62,7 +62,7 @@ static struct rc_map_table msi_tvanywhere_plus[] = { + { 0x13, KEY_AGAIN }, /* Recall */ + + { 0x1e, KEY_POWER }, /* Power */ +- { 0x07, KEY_TUNER }, /* Source */ ++ { 0x07, KEY_VIDEO }, /* Source */ + { 0x1c, KEY_SEARCH }, /* Scan */ + { 0x18, KEY_MUTE }, /* Mute */ + +diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c +index 3e6f077..ddae20e 100644 +--- a/drivers/media/rc/keymaps/rc-nebula.c ++++ b/drivers/media/rc/keymaps/rc-nebula.c +@@ -27,7 +27,7 @@ static struct rc_map_table nebula[] = { + { 0x0b, KEY_AUX }, + { 0x0c, KEY_DVD }, + { 0x0d, KEY_POWER }, +- { 0x0e, KEY_MHP }, /* labelled 'Picture' */ ++ { 0x0e, KEY_CAMERA }, /* labelled 'Picture' */ + { 0x0f, KEY_AUDIO }, + { 0x10, KEY_INFO }, + { 0x11, KEY_F13 }, /* 16:9 */ +diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c +index 629ee9d..f1c1281 100644 +--- a/drivers/media/rc/keymaps/rc-norwood.c ++++ b/drivers/media/rc/keymaps/rc-norwood.c +@@ -29,7 +29,7 @@ static struct rc_map_table norwood[] = { + { 0x28, KEY_8 }, + { 0x29, KEY_9 }, + +- { 0x78, KEY_TUNER }, /* Video Source */ ++ { 0x78, KEY_VIDEO }, /* Video Source */ + { 0x2c, KEY_EXIT }, /* Open/Close software */ + { 0x2a, KEY_SELECT }, /* 2 Digit Select */ + { 0x69, KEY_AGAIN }, /* Recall */ +diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c +index fa5ae59..7cdef6e 100644 +--- a/drivers/media/rc/keymaps/rc-pctv-sedna.c ++++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c +@@ -36,7 +36,7 @@ static struct rc_map_table pctv_sedna[] = { + { 0x0e, KEY_STOP }, + { 0x0f, KEY_PREVIOUSSONG }, + { 0x10, KEY_ZOOM }, +- { 0x11, KEY_TUNER }, /* Source */ ++ { 0x11, KEY_VIDEO }, /* Source */ + { 0x12, KEY_POWER }, + { 0x13, KEY_MUTE }, + { 0x15, KEY_CHANNELDOWN }, +diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c +index 8d9f664..125fc39 100644 +--- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c ++++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c +@@ -34,7 +34,7 @@ static struct rc_map_table pixelview_mk12[] = { + { 0x866b13, KEY_AGAIN }, /* loop */ + { 0x866b10, KEY_DIGITS }, /* +100 */ + +- { 0x866b00, KEY_MEDIA }, /* source */ ++ { 0x866b00, KEY_VIDEO }, /* source */ + { 0x866b18, KEY_MUTE }, /* mute */ + { 0x866b19, KEY_CAMERA }, /* snapshot */ + { 0x866b1a, KEY_SEARCH }, /* scan */ +diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c +index 777a700..bd78d6a 100644 +--- a/drivers/media/rc/keymaps/rc-pixelview-new.c ++++ b/drivers/media/rc/keymaps/rc-pixelview-new.c +@@ -33,7 +33,7 @@ static struct rc_map_table pixelview_new[] = { + { 0x3e, KEY_0 }, + + { 0x1c, KEY_AGAIN }, /* LOOP */ +- { 0x3f, KEY_MEDIA }, /* Source */ ++ { 0x3f, KEY_VIDEO }, /* Source */ + { 0x1f, KEY_LAST }, /* +100 */ + { 0x1b, KEY_MUTE }, + +diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c +index 0ec5988..06187e7 100644 +--- a/drivers/media/rc/keymaps/rc-pixelview.c ++++ b/drivers/media/rc/keymaps/rc-pixelview.c +@@ -15,7 +15,7 @@ + static struct rc_map_table pixelview[] = { + + { 0x1e, KEY_POWER }, /* power */ +- { 0x07, KEY_MEDIA }, /* source */ ++ { 0x07, KEY_VIDEO }, /* source */ + { 0x1c, KEY_SEARCH }, /* scan */ + + +diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c +index 83a418d..5e8beee 100644 +--- a/drivers/media/rc/keymaps/rc-pv951.c ++++ b/drivers/media/rc/keymaps/rc-pv951.c +@@ -46,10 +46,10 @@ static struct rc_map_table pv951[] = { + { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ + + /* Not sure what to do with these ones! */ +- { 0x0f, KEY_SELECT }, /* SOURCE */ ++ { 0x0f, KEY_VIDEO }, /* SOURCE */ + { 0x0a, KEY_KPPLUS }, /* +100 */ + { 0x14, KEY_EQUAL }, /* SYNC */ +- { 0x1c, KEY_MEDIA }, /* PC/TV */ ++ { 0x1c, KEY_TV }, /* PC/TV */ + }; + + static struct rc_map_list pv951_map = { +diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c +deleted file mode 100644 +index dfc9b15..0000000 +--- a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c ++++ /dev/null +@@ -1,141 +0,0 @@ +-/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller +- * +- * keymap imported from ir-keymaps.c +- * +- * Copyright (c) 2010 by Mauro Carvalho Chehab +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- */ +- +-#include +- +-/* +- * Hauppauge:the newer, gray remotes (seems there are multiple +- * slightly different versions), shipped with cx88+ivtv cards. +- * +- * This table contains the complete RC5 code, instead of just the data part +- */ +- +-static struct rc_map_table rc5_hauppauge_new[] = { +- /* Keys 0 to 9 */ +- { 0x1e00, KEY_0 }, +- { 0x1e01, KEY_1 }, +- { 0x1e02, KEY_2 }, +- { 0x1e03, KEY_3 }, +- { 0x1e04, KEY_4 }, +- { 0x1e05, KEY_5 }, +- { 0x1e06, KEY_6 }, +- { 0x1e07, KEY_7 }, +- { 0x1e08, KEY_8 }, +- { 0x1e09, KEY_9 }, +- +- { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ +- { 0x1e0b, KEY_RED }, /* red button */ +- { 0x1e0c, KEY_RADIO }, +- { 0x1e0d, KEY_MENU }, +- { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ +- { 0x1e0f, KEY_MUTE }, +- { 0x1e10, KEY_VOLUMEUP }, +- { 0x1e11, KEY_VOLUMEDOWN }, +- { 0x1e12, KEY_PREVIOUS }, /* previous channel */ +- { 0x1e14, KEY_UP }, +- { 0x1e15, KEY_DOWN }, +- { 0x1e16, KEY_LEFT }, +- { 0x1e17, KEY_RIGHT }, +- { 0x1e18, KEY_VIDEO }, /* Videos */ +- { 0x1e19, KEY_AUDIO }, /* Music */ +- /* 0x1e1a: Pictures - presume this means +- "Multimedia Home Platform" - +- no "PICTURES" key in input.h +- */ +- { 0x1e1a, KEY_MHP }, +- +- { 0x1e1b, KEY_EPG }, /* Guide */ +- { 0x1e1c, KEY_TV }, +- { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ +- { 0x1e1f, KEY_EXIT }, /* back/exit */ +- { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ +- { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ +- { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ +- { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ +- { 0x1e25, KEY_ENTER }, /* OK */ +- { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ +- { 0x1e29, KEY_BLUE }, /* blue key */ +- { 0x1e2e, KEY_GREEN }, /* green button */ +- { 0x1e30, KEY_PAUSE }, /* pause */ +- { 0x1e32, KEY_REWIND }, /* backward << */ +- { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ +- { 0x1e35, KEY_PLAY }, +- { 0x1e36, KEY_STOP }, +- { 0x1e37, KEY_RECORD }, /* recording */ +- { 0x1e38, KEY_YELLOW }, /* yellow key */ +- { 0x1e3b, KEY_SELECT }, /* top right button */ +- { 0x1e3c, KEY_ZOOM }, /* full */ +- { 0x1e3d, KEY_POWER }, /* system power (green button) */ +- +- /* Keycodes for DSR-0112 remote bundled with Haupauge MiniStick */ +- { 0x1d00, KEY_0 }, +- { 0x1d01, KEY_1 }, +- { 0x1d02, KEY_2 }, +- { 0x1d03, KEY_3 }, +- { 0x1d04, KEY_4 }, +- { 0x1d05, KEY_5 }, +- { 0x1d06, KEY_6 }, +- { 0x1d07, KEY_7 }, +- { 0x1d08, KEY_8 }, +- { 0x1d09, KEY_9 }, +- { 0x1d0a, KEY_TEXT }, +- { 0x1d0d, KEY_MENU }, +- { 0x1d0f, KEY_MUTE }, +- { 0x1d10, KEY_VOLUMEUP }, +- { 0x1d11, KEY_VOLUMEDOWN }, +- { 0x1d12, KEY_PREVIOUS }, /* Prev.Ch .. ??? */ +- { 0x1d14, KEY_UP }, +- { 0x1d15, KEY_DOWN }, +- { 0x1d16, KEY_LEFT }, +- { 0x1d17, KEY_RIGHT }, +- { 0x1d1c, KEY_TV }, +- { 0x1d1e, KEY_NEXT }, /* >| */ +- { 0x1d1f, KEY_EXIT }, +- { 0x1d20, KEY_CHANNELUP }, +- { 0x1d21, KEY_CHANNELDOWN }, +- { 0x1d24, KEY_LAST }, /* <| */ +- { 0x1d25, KEY_OK }, +- { 0x1d30, KEY_PAUSE }, +- { 0x1d32, KEY_REWIND }, +- { 0x1d34, KEY_FASTFORWARD }, +- { 0x1d35, KEY_PLAY }, +- { 0x1d36, KEY_STOP }, +- { 0x1d37, KEY_RECORD }, +- { 0x1d3b, KEY_GOTO }, +- { 0x1d3d, KEY_POWER }, +- { 0x1d3f, KEY_HOME }, +-}; +- +-static struct rc_map_list rc5_hauppauge_new_map = { +- .map = { +- .scan = rc5_hauppauge_new, +- .size = ARRAY_SIZE(rc5_hauppauge_new), +- .rc_type = RC_TYPE_RC5, +- .name = RC_MAP_RC5_HAUPPAUGE_NEW, +- } +-}; +- +-static int __init init_rc_map_rc5_hauppauge_new(void) +-{ +- return rc_map_register(&rc5_hauppauge_new_map); +-} +- +-static void __exit exit_rc_map_rc5_hauppauge_new(void) +-{ +- rc_map_unregister(&rc5_hauppauge_new_map); +-} +- +-module_init(init_rc_map_rc5_hauppauge_new) +-module_exit(exit_rc_map_rc5_hauppauge_new) +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Mauro Carvalho Chehab "); +diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c +deleted file mode 100644 +index 4fcef9f..0000000 +--- a/drivers/media/rc/keymaps/rc-rc5-tv.c ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* rc5-tv.h - Keytable for rc5_tv Remote Controller +- * +- * keymap imported from ir-keymaps.c +- * +- * Copyright (c) 2010 by Mauro Carvalho Chehab +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- */ +- +-#include +- +-/* generic RC5 keytable */ +-/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ +-/* used by old (black) Hauppauge remotes */ +- +-static struct rc_map_table rc5_tv[] = { +- /* Keys 0 to 9 */ +- { 0x00, KEY_0 }, +- { 0x01, KEY_1 }, +- { 0x02, KEY_2 }, +- { 0x03, KEY_3 }, +- { 0x04, KEY_4 }, +- { 0x05, KEY_5 }, +- { 0x06, KEY_6 }, +- { 0x07, KEY_7 }, +- { 0x08, KEY_8 }, +- { 0x09, KEY_9 }, +- +- { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ +- { 0x0c, KEY_POWER }, /* standby */ +- { 0x0d, KEY_MUTE }, /* mute / demute */ +- { 0x0f, KEY_TV }, /* display */ +- { 0x10, KEY_VOLUMEUP }, +- { 0x11, KEY_VOLUMEDOWN }, +- { 0x12, KEY_BRIGHTNESSUP }, +- { 0x13, KEY_BRIGHTNESSDOWN }, +- { 0x1e, KEY_SEARCH }, /* search + */ +- { 0x20, KEY_CHANNELUP }, /* channel / program + */ +- { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ +- { 0x22, KEY_CHANNEL }, /* alt / channel */ +- { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ +- { 0x26, KEY_SLEEP }, /* sleeptimer */ +- { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ +- { 0x30, KEY_PAUSE }, +- { 0x32, KEY_REWIND }, +- { 0x33, KEY_GOTO }, +- { 0x35, KEY_PLAY }, +- { 0x36, KEY_STOP }, +- { 0x37, KEY_RECORD }, /* recording */ +- { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ +- { 0x3d, KEY_SUSPEND }, /* system standby */ +- +-}; +- +-static struct rc_map_list rc5_tv_map = { +- .map = { +- .scan = rc5_tv, +- .size = ARRAY_SIZE(rc5_tv), +- .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ +- .name = RC_MAP_RC5_TV, +- } +-}; +- +-static int __init init_rc_map_rc5_tv(void) +-{ +- return rc_map_register(&rc5_tv_map); +-} +- +-static void __exit exit_rc_map_rc5_tv(void) +-{ +- rc_map_unregister(&rc5_tv_map); +-} +- +-module_init(init_rc_map_rc5_tv) +-module_exit(exit_rc_map_rc5_tv) +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Mauro Carvalho Chehab "); +diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c +index 2f5dc06..8dd519e 100644 +--- a/drivers/media/rc/keymaps/rc-rc6-mce.c ++++ b/drivers/media/rc/keymaps/rc-rc6-mce.c +@@ -30,7 +30,7 @@ static struct rc_map_table rc6_mce[] = { + { 0x800f040a, KEY_DELETE }, + { 0x800f040b, KEY_ENTER }, + { 0x800f040c, KEY_POWER }, /* PC Power */ +- { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ ++ { 0x800f040d, KEY_LEFTMETA }, /* Windows MCE button */ + { 0x800f040e, KEY_MUTE }, + { 0x800f040f, KEY_INFO }, + +diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c +index 2d14598..6813d11 100644 +--- a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c ++++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c +@@ -35,7 +35,7 @@ static struct rc_map_table real_audio_220_32_keys[] = { + { 0x15, KEY_CHANNELDOWN}, + { 0x16, KEY_ENTER}, + +- { 0x11, KEY_LIST}, /* Source */ ++ { 0x11, KEY_VIDEO}, /* Source */ + { 0x0d, KEY_AUDIO}, /* stereo */ + + { 0x0f, KEY_PREVIOUS}, /* Prev */ +diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c +index 2747db4..0062ca2 100644 +--- a/drivers/media/rc/keymaps/rc-winfast.c ++++ b/drivers/media/rc/keymaps/rc-winfast.c +@@ -27,15 +27,15 @@ static struct rc_map_table winfast[] = { + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + +- { 0x00, KEY_POWER }, ++ { 0x00, KEY_POWER2 }, + { 0x1b, KEY_AUDIO }, /* Audio Source */ + { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ + { 0x1e, KEY_VIDEO }, /* Video Source */ + { 0x16, KEY_INFO }, /* Display information */ +- { 0x04, KEY_VOLUMEUP }, +- { 0x08, KEY_VOLUMEDOWN }, +- { 0x0c, KEY_CHANNELUP }, +- { 0x10, KEY_CHANNELDOWN }, ++ { 0x04, KEY_LEFT }, ++ { 0x08, KEY_RIGHT }, ++ { 0x0c, KEY_UP }, ++ { 0x10, KEY_DOWN }, + { 0x03, KEY_ZOOM }, /* fullscreen */ + { 0x1f, KEY_TEXT }, /* closed caption/teletext */ + { 0x20, KEY_SLEEP }, +@@ -47,7 +47,7 @@ static struct rc_map_table winfast[] = { + { 0x2e, KEY_BLUE }, + { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ + { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ +- { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ ++ { 0x2a, KEY_TV2 }, /* PIP (Picture in picture */ + { 0x21, KEY_DOT }, + { 0x13, KEY_ENTER }, + { 0x11, KEY_LAST }, /* Recall (last channel */ +@@ -57,7 +57,7 @@ static struct rc_map_table winfast[] = { + { 0x25, KEY_TIME }, /* Time Shifting */ + { 0x26, KEY_STOP }, + { 0x27, KEY_RECORD }, +- { 0x28, KEY_SAVE }, /* Screenshot */ ++ { 0x28, KEY_CAMERA }, /* Screenshot */ + { 0x2f, KEY_MENU }, + { 0x30, KEY_CANCEL }, + { 0x31, KEY_CHANNEL }, /* Channel Surf */ +@@ -70,10 +70,10 @@ static struct rc_map_table winfast[] = { + { 0x38, KEY_DVD }, + + { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ +- { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ +- { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ +- { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ +- { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ ++ { 0x3e, KEY_VOLUMEUP }, /* MCE +VOL, on Y04G0033 */ ++ { 0x3a, KEY_VOLUMEDOWN }, /* MCE -VOL, on Y04G0033 */ ++ { 0x3b, KEY_CHANNELUP }, /* MCE +CH, on Y04G0033 */ ++ { 0x3f, KEY_CHANNELDOWN } /* MCE -CH, on Y04G0033 */ + }; + + static struct rc_map_list winfast_map = { +diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c +index e4f8eac..044fb7a 100644 +--- a/drivers/media/rc/mceusb.c ++++ b/drivers/media/rc/mceusb.c +@@ -186,7 +186,7 @@ static const struct mceusb_model mceusb_model[] = { + * remotes, but we should have something handy, + * to allow testing it + */ +- .rc_map = RC_MAP_RC5_HAUPPAUGE_NEW, ++ .rc_map = RC_MAP_HAUPPAUGE, + .name = "Conexant Hybrid TV (cx231xx) MCE IR", + }, + [CX_HYBRID_TV] = { +@@ -261,7 +261,7 @@ static struct usb_device_id mceusb_dev_table[] = { + .driver_info = MCE_GEN2_TX_INV }, + /* Topseed eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TOPSEED, 0x0011), +- .driver_info = MCE_GEN2_TX_INV }, ++ .driver_info = MCE_GEN3 }, + /* Ricavision internal Infrared Transceiver */ + { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, + /* Itron ione Libra Q-11 */ +diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c +index c330fb9..040aaa8 100644 +--- a/drivers/media/video/cx18/cx18-i2c.c ++++ b/drivers/media/video/cx18/cx18-i2c.c +@@ -96,7 +96,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, + /* Our default information for ir-kbd-i2c.c to use */ + switch (hw) { + case CX18_HW_Z8F0811_IR_RX_HAUP: +- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ init_data->ir_codes = RC_MAP_HAUPPAUGE; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = cx->card_name; +diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c +index 199b996..e97cafd 100644 +--- a/drivers/media/video/cx23885/cx23885-input.c ++++ b/drivers/media/video/cx23885/cx23885-input.c +@@ -264,7 +264,7 @@ int cx23885_input_init(struct cx23885_dev *dev) + driver_type = RC_DRIVER_IR_RAW; + allowed_protos = RC_TYPE_ALL; + /* The grey Hauppauge RC-5 remote */ +- rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; ++ rc_map = RC_MAP_HAUPPAUGE; + break; + case CX23885_BOARD_TEVII_S470: + /* Integrated CX23885 IR controller */ +diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c +index fbfbba5..c820e2f 100644 +--- a/drivers/media/video/cx88/cx88-input.c ++++ b/drivers/media/video/cx88/cx88-input.c +@@ -283,7 +283,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: + case CX88_BOARD_HAUPPAUGE_IRONLY: +- ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ ir_codes = RC_MAP_HAUPPAUGE; + ir->sampling = 1; + break; + case CX88_BOARD_WINFAST_DTV2000H: +@@ -604,7 +604,7 @@ void cx88_i2c_init_ir(struct cx88_core *core) + if (*addrp == 0x71) { + /* Hauppauge XVR */ + core->init_data.name = "cx88 Hauppauge XVR remote"; +- core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ core->init_data.ir_codes = RC_MAP_HAUPPAUGE; + core->init_data.type = RC_TYPE_RC5; + core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + +diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c +index 87f77a3..69fcea8 100644 +--- a/drivers/media/video/em28xx/em28xx-cards.c ++++ b/drivers/media/video/em28xx/em28xx-cards.c +@@ -834,7 +834,7 @@ struct em28xx_board em28xx_boards[] = { + .mts_firmware = 1, + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +- .ir_codes = RC_MAP_HAUPPAUGE_NEW, ++ .ir_codes = RC_MAP_HAUPPAUGE, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, +@@ -859,7 +859,7 @@ struct em28xx_board em28xx_boards[] = { + .tuner_type = TUNER_XC2028, + .tuner_gpio = default_tuner_gpio, + .mts_firmware = 1, +- .ir_codes = RC_MAP_HAUPPAUGE_NEW, ++ .ir_codes = RC_MAP_HAUPPAUGE, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, +@@ -885,7 +885,7 @@ struct em28xx_board em28xx_boards[] = { + .mts_firmware = 1, + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +- .ir_codes = RC_MAP_HAUPPAUGE_NEW, ++ .ir_codes = RC_MAP_HAUPPAUGE, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, +@@ -911,7 +911,7 @@ struct em28xx_board em28xx_boards[] = { + .mts_firmware = 1, + .has_dvb = 1, + .dvb_gpio = hauppauge_wintv_hvr_900_digital, +- .ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW, ++ .ir_codes = RC_MAP_HAUPPAUGE, + .decoder = EM28XX_TVP5150, + .input = { { + .type = EM28XX_VMUX_TELEVISION, +@@ -2430,7 +2430,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) + dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; + break; + case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: +- dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; ++ dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; + dev->init_data.get_key = em28xx_get_key_em_haup; + dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; + break; +diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c +index e53fa55..2a1ac28 100644 +--- a/drivers/media/video/hdpvr/hdpvr-i2c.c ++++ b/drivers/media/video/hdpvr/hdpvr-i2c.c +@@ -52,25 +52,36 @@ struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev) + }; + + /* Our default information for ir-kbd-i2c.c to use */ +- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ init_data->ir_codes = RC_MAP_HAUPPAUGE; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = "HD-PVR"; ++ init_data->polling_interval = 405; /* ms, duplicated from Windows */ + hdpvr_ir_rx_i2c_board_info.platform_data = init_data; + + return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info); + } + + static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, +- unsigned char addr, char *data, int len) ++ unsigned char addr, char *wdata, int wlen, ++ char *data, int len) + { + int ret; + +- if (len > sizeof(dev->i2c_buf)) ++ if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf))) + return -EINVAL; + +- ret = usb_control_msg(dev->udev, +- usb_rcvctrlpipe(dev->udev, 0), ++ if (wlen) { ++ memcpy(&dev->i2c_buf, wdata, wlen); ++ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), ++ REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, ++ (bus << 8) | addr, 0, &dev->i2c_buf, ++ wlen, 1000); ++ if (ret < 0) ++ return ret; ++ } ++ ++ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), + REQTYPE_I2C_READ, CTRL_READ_REQUEST, + (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); + +@@ -92,16 +103,14 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus, + return -EINVAL; + + memcpy(&dev->i2c_buf, data, len); +- ret = usb_control_msg(dev->udev, +- usb_sndctrlpipe(dev->udev, 0), ++ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), + REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, + (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); + + if (ret < 0) + return ret; + +- ret = usb_control_msg(dev->udev, +- usb_rcvctrlpipe(dev->udev, 0), ++ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), + REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, + 0, 0, &dev->i2c_buf, 2, 1000); + +@@ -117,24 +126,49 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, + int num) + { + struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); +- int retval = 0, i, addr; ++ int retval = 0, addr; + + if (num <= 0) + return 0; + + mutex_lock(&dev->i2c_mutex); + +- for (i = 0; i < num && !retval; i++) { +- addr = msgs[i].addr << 1; ++ addr = msgs[0].addr << 1; + +- if (msgs[i].flags & I2C_M_RD) +- retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf, +- msgs[i].len); ++ if (num == 1) { ++ if (msgs[0].flags & I2C_M_RD) ++ retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0, ++ msgs[0].buf, msgs[0].len); + else +- retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf, +- msgs[i].len); ++ retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf, ++ msgs[0].len); ++ } else if (num == 2) { ++ if (msgs[0].addr != msgs[1].addr) { ++ v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer " ++ "with conflicting target addresses\n"); ++ retval = -EINVAL; ++ goto out; ++ } ++ ++ if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) { ++ v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with " ++ "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD, ++ msgs[1].flags & I2C_M_RD); ++ retval = -EINVAL; ++ goto out; ++ } ++ ++ /* ++ * Write followed by atomic read is the only complex xfer that ++ * we actually support here. ++ */ ++ retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len, ++ msgs[1].buf, msgs[1].len); ++ } else { ++ v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num); + } + ++out: + mutex_unlock(&dev->i2c_mutex); + + return retval ? retval : num; +@@ -158,11 +192,11 @@ static struct i2c_adapter hdpvr_i2c_adapter_template = { + + static int hdpvr_activate_ir(struct hdpvr_device *dev) + { +- char buffer[8]; ++ char buffer[2]; + + mutex_lock(&dev->i2c_mutex); + +- hdpvr_i2c_read(dev, 0, 0x54, buffer, 1); ++ hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1); + + buffer[0] = 0; + buffer[1] = 0x8; +diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c +index a221ad6..3ab875d 100644 +--- a/drivers/media/video/ir-kbd-i2c.c ++++ b/drivers/media/video/ir-kbd-i2c.c +@@ -55,10 +55,6 @@ + static int debug; + module_param(debug, int, 0644); /* debug level (0,1,2) */ + +-static int hauppauge; +-module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ +-MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); +- + + #define MODULE_NAME "ir-kbd-i2c" + #define dprintk(level, fmt, arg...) if (debug >= level) \ +@@ -105,10 +101,6 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, + /* invalid key press */ + return 0; + +- if (dev!=0x1e && dev!=0x1f) +- /* not a hauppauge remote */ +- return 0; +- + if (!range) + code += 64; + +@@ -116,7 +108,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, + start, range, toggle, dev, code); + + /* return key */ +- *ir_key = code; ++ *ir_key = (dev << 8) | code; + *ir_raw = ircode; + return 1; + } +@@ -312,11 +304,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) + name = "Hauppauge"; + ir->get_key = get_key_haup; + rc_type = RC_TYPE_RC5; +- if (hauppauge == 1) { +- ir_codes = RC_MAP_HAUPPAUGE_NEW; +- } else { +- ir_codes = RC_MAP_RC5_TV; +- } ++ ir_codes = RC_MAP_HAUPPAUGE; + break; + case 0x30: + name = "KNC One"; +@@ -340,7 +328,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) + name = "Hauppauge/Zilog Z8"; + ir->get_key = get_key_haup_xvr; + rc_type = RC_TYPE_RC5; +- ir_codes = hauppauge ? RC_MAP_HAUPPAUGE_NEW : RC_MAP_RC5_TV; ++ ir_codes = RC_MAP_HAUPPAUGE; + break; + } + +diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c +index 9fb86a0..d47f41a 100644 +--- a/drivers/media/video/ivtv/ivtv-i2c.c ++++ b/drivers/media/video/ivtv/ivtv-i2c.c +@@ -205,15 +205,14 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) + break; + case IVTV_HW_I2C_IR_RX_HAUP_EXT: + case IVTV_HW_I2C_IR_RX_HAUP_INT: +- /* Default to old black remote */ +- init_data->ir_codes = RC_MAP_RC5_TV; ++ init_data->ir_codes = RC_MAP_HAUPPAUGE; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; + init_data->type = RC_TYPE_RC5; + init_data->name = itv->card_name; + break; + case IVTV_HW_Z8F0811_IR_RX_HAUP: + /* Default to grey remote */ +- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ init_data->ir_codes = RC_MAP_HAUPPAUGE; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = itv->card_name; +diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +index 451ecd4..e72d510 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c ++++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +@@ -578,7 +578,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) + switch (hdw->ir_scheme_active) { + case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */ + case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */ +- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ init_data->ir_codes = RC_MAP_HAUPPAUGE; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; + init_data->type = RC_TYPE_RC5; + init_data->name = hdw->hdw_desc->description; +@@ -593,7 +593,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) + break; + case PVR2_IR_SCHEME_ZILOG: /* HVR-1950 style */ + case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */ +- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ init_data->ir_codes = RC_MAP_HAUPPAUGE; + init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; + init_data->type = RC_TYPE_RC5; + init_data->name = hdw->hdw_desc->description; +diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c +index 790d667..be1c2a2 100644 +--- a/drivers/media/video/saa7134/saa7134-input.c ++++ b/drivers/media/video/saa7134/saa7134-input.c +@@ -893,7 +893,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) + case SAA7134_BOARD_HAUPPAUGE_HVR1110: + dev->init_data.name = "HVR 1110"; + dev->init_data.get_key = get_key_hvr1110; +- dev->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; + info.addr = 0x71; + break; + case SAA7134_BOARD_BEHOLD_607FM_MK3: +diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig +index cdaff59..526ec0f 100644 +--- a/drivers/staging/lirc/Kconfig ++++ b/drivers/staging/lirc/Kconfig +@@ -32,18 +32,6 @@ config LIRC_IMON + + Current generation iMON devices use the input layer imon driver. + +-config LIRC_IT87 +- tristate "ITE IT87XX CIR Port Receiver" +- depends on LIRC && PNP +- help +- Driver for the ITE IT87xx IR Receiver +- +-config LIRC_ITE8709 +- tristate "ITE8709 CIR Port Receiver" +- depends on LIRC && PNP +- help +- Driver for the ITE8709 IR Receiver +- + config LIRC_PARALLEL + tristate "Homebrew Parallel Port Receiver" + depends on LIRC && PARPORT +diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile +index 94af218..d76b0fa 100644 +--- a/drivers/staging/lirc/Makefile ++++ b/drivers/staging/lirc/Makefile +@@ -6,8 +6,6 @@ + obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o + obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o + obj-$(CONFIG_LIRC_IMON) += lirc_imon.o +-obj-$(CONFIG_LIRC_IT87) += lirc_it87.o +-obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o + obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o + obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o + obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o +diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog +index 2d0263f..a97800a 100644 +--- a/drivers/staging/lirc/TODO.lirc_zilog ++++ b/drivers/staging/lirc/TODO.lirc_zilog +@@ -1,34 +1,33 @@ +-1. Both ir-kbd-i2c and lirc_zilog provide support for RX events. +-The 'tx_only' lirc_zilog module parameter will allow ir-kbd-i2c +-and lirc_zilog to coexist in the kernel, if the user requires such a set-up. +-However the IR unit will not work well without coordination between the +-two modules. A shared mutex, for transceiver access locking, needs to be +-supplied by bridge drivers, in struct IR_i2_init_data, to both ir-kbd-i2c +-and lirc_zilog, before they will coexist usefully. This should be fixed +-before moving out of staging. +- +-2. References and locking need careful examination. For cx18 and ivtv PCI +-cards, which are not easily "hot unplugged", the imperfect state of reference +-counting and locking is acceptable if not correct. For USB connected units +-like HD PVR, PVR USB2, HVR-1900, and HVR1950, the likelyhood of an Ooops on +-unplug is probably great. Proper reference counting and locking needs to be +-implemented before this module is moved out of staging. +- +-3. The binding between hdpvr and lirc_zilog is currently disabled, +-due to an OOPS reported a few years ago when both the hdpvr and cx18 +-drivers were loaded in his system. More details can be seen at: +- http://www.mail-archive.com/linux-media@vger.kernel.org/msg09163.html +-More tests need to be done, in order to fix the reported issue. +- +-4. In addition to providing a shared mutex for transceiver access +-locking, bridge drivers, if able, should provide a chip reset() callback ++1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for ++the chips supported by lirc_zilog. Before moving lirc_zilog out of staging: ++ ++a. ir-kbd-i2c needs a module parameter added to allow the user to tell ++ ir-kbd-i2c to ignore Z8 IR units. ++ ++b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c ++ does. ++ ++ ++2. lirc_zilog module ref-counting need examination. It has not been ++verified that cdev and lirc_dev will take the proper module references on ++lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node ++is open. ++ ++(The good news is ref-counting of lirc_zilog internal structures appears to be ++complete. Testing has shown the cx18 module can be unloaded out from under ++irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse ++effects. The cx18 module could then be reloaded and irw properly began ++receiving button presses again and ir_send worked without error.) ++ ++ ++3. Bridge drivers, if able, should provide a chip reset() callback + to lirc_zilog via struct IR_i2c_init_data. cx18 and ivtv already have routines +-to perform Z8 chip resets via GPIO manipulations. This will allow lirc_zilog ++to perform Z8 chip resets via GPIO manipulations. This would allow lirc_zilog + to bring the chip back to normal when it hangs, in the same places the + original lirc_pvr150 driver code does. This is not strictly needed, so it + is not required to move lirc_zilog out of staging. + +-5. Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed ++Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed + and installed on Hauppauge products. When working on either module, developers + must consider at least the following bridge drivers which mention an IR Rx unit + at address 0x71 (indicative of a Z8): +diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c +index 235cab0..4039eda 100644 +--- a/drivers/staging/lirc/lirc_imon.c ++++ b/drivers/staging/lirc/lirc_imon.c +@@ -379,7 +379,7 @@ static ssize_t vfd_write(struct file *file, const char *buf, + struct imon_context *context; + const unsigned char vfd_packet6[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; +- int *data_buf; ++ int *data_buf = NULL; + + context = file->private_data; + if (!context) { +diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c +deleted file mode 100644 +index 5938616..0000000 +--- a/drivers/staging/lirc/lirc_it87.c ++++ /dev/null +@@ -1,1027 +0,0 @@ +-/* +- * LIRC driver for ITE IT8712/IT8705 CIR port +- * +- * Copyright (C) 2001 Hans-Gunter Lutke Uphues +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License as +- * published by the Free Software Foundation; either version 2 of the +- * License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +- * USA +- * +- * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based +- * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula +- * +- * Attention: Sendmode only tested with debugging logs +- * +- * 2001/02/27 Christoph Bartelmus : +- * reimplemented read function +- * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, +- * based on work of the following member of the Outertrack Digimatrix +- * Forum: Art103 +- * 2009/12/24 James Edwards implemeted support +- * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the +- * chip identifies as 18. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +- +-#include "lirc_it87.h" +- +-#ifdef LIRC_IT87_DIGIMATRIX +-static int digimatrix = 1; +-static int it87_freq = 36; /* kHz */ +-static int irq = 9; +-#else +-static int digimatrix; +-static int it87_freq = 38; /* kHz */ +-static int irq = IT87_CIR_DEFAULT_IRQ; +-#endif +- +-static unsigned long it87_bits_in_byte_out; +-static unsigned long it87_send_counter; +-static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; +- +-#define RBUF_LEN 1024 +- +-#define LIRC_DRIVER_NAME "lirc_it87" +- +-/* timeout for sequences in jiffies (=5/100s) */ +-/* must be longer than TIME_CONST */ +-#define IT87_TIMEOUT (HZ*5/100) +- +-/* module parameters */ +-static int debug; +-#define dprintk(fmt, args...) \ +- do { \ +- if (debug) \ +- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ +- fmt, ## args); \ +- } while (0) +- +-static int io = IT87_CIR_DEFAULT_IOBASE; +-/* receiver demodulator default: off */ +-static int it87_enable_demodulator; +- +-static int timer_enabled; +-static DEFINE_SPINLOCK(timer_lock); +-static struct timer_list timerlist; +-/* time of last signal change detected */ +-static struct timeval last_tv = {0, 0}; +-/* time of last UART data ready interrupt */ +-static struct timeval last_intr_tv = {0, 0}; +-static int last_value; +- +-static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); +- +-static DEFINE_SPINLOCK(hardware_lock); +-static DEFINE_SPINLOCK(dev_lock); +-static bool device_open; +- +-static int rx_buf[RBUF_LEN]; +-unsigned int rx_tail, rx_head; +- +-static struct pnp_driver it87_pnp_driver; +- +-/* SECTION: Prototypes */ +- +-/* Communication with user-space */ +-static int lirc_open(struct inode *inode, struct file *file); +-static int lirc_close(struct inode *inode, struct file *file); +-static unsigned int lirc_poll(struct file *file, poll_table *wait); +-static ssize_t lirc_read(struct file *file, char *buf, +- size_t count, loff_t *ppos); +-static ssize_t lirc_write(struct file *file, const char *buf, +- size_t n, loff_t *pos); +-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); +-static void add_read_queue(int flag, unsigned long val); +-static int init_chrdev(void); +-static void drop_chrdev(void); +-/* Hardware */ +-static irqreturn_t it87_interrupt(int irq, void *dev_id); +-static void send_space(unsigned long len); +-static void send_pulse(unsigned long len); +-static void init_send(void); +-static void terminate_send(unsigned long len); +-static int init_hardware(void); +-static void drop_hardware(void); +-/* Initialisation */ +-static int init_port(void); +-static void drop_port(void); +- +- +-/* SECTION: Communication with user-space */ +- +-static int lirc_open(struct inode *inode, struct file *file) +-{ +- spin_lock(&dev_lock); +- if (device_open) { +- spin_unlock(&dev_lock); +- return -EBUSY; +- } +- device_open = true; +- spin_unlock(&dev_lock); +- return 0; +-} +- +- +-static int lirc_close(struct inode *inode, struct file *file) +-{ +- spin_lock(&dev_lock); +- device_open = false; +- spin_unlock(&dev_lock); +- return 0; +-} +- +- +-static unsigned int lirc_poll(struct file *file, poll_table *wait) +-{ +- poll_wait(file, &lirc_read_queue, wait); +- if (rx_head != rx_tail) +- return POLLIN | POLLRDNORM; +- return 0; +-} +- +- +-static ssize_t lirc_read(struct file *file, char *buf, +- size_t count, loff_t *ppos) +-{ +- int n = 0; +- int retval = 0; +- +- while (n < count) { +- if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { +- retval = -EAGAIN; +- break; +- } +- retval = wait_event_interruptible(lirc_read_queue, +- rx_head != rx_tail); +- if (retval) +- break; +- +- if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), +- sizeof(int))) { +- retval = -EFAULT; +- break; +- } +- rx_head = (rx_head + 1) & (RBUF_LEN - 1); +- n += sizeof(int); +- } +- if (n) +- return n; +- return retval; +-} +- +- +-static ssize_t lirc_write(struct file *file, const char *buf, +- size_t n, loff_t *pos) +-{ +- int i = 0; +- int *tx_buf; +- +- if (n % sizeof(int)) +- return -EINVAL; +- tx_buf = memdup_user(buf, n); +- if (IS_ERR(tx_buf)) +- return PTR_ERR(tx_buf); +- n /= sizeof(int); +- init_send(); +- while (1) { +- if (i >= n) +- break; +- if (tx_buf[i]) +- send_pulse(tx_buf[i]); +- i++; +- if (i >= n) +- break; +- if (tx_buf[i]) +- send_space(tx_buf[i]); +- i++; +- } +- terminate_send(tx_buf[i - 1]); +- kfree(tx_buf); +- return n; +-} +- +- +-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +-{ +- int retval = 0; +- __u32 value = 0; +- unsigned long hw_flags; +- +- if (cmd == LIRC_GET_FEATURES) +- value = LIRC_CAN_SEND_PULSE | +- LIRC_CAN_SET_SEND_CARRIER | +- LIRC_CAN_REC_MODE2; +- else if (cmd == LIRC_GET_SEND_MODE) +- value = LIRC_MODE_PULSE; +- else if (cmd == LIRC_GET_REC_MODE) +- value = LIRC_MODE_MODE2; +- +- switch (cmd) { +- case LIRC_GET_FEATURES: +- case LIRC_GET_SEND_MODE: +- case LIRC_GET_REC_MODE: +- retval = put_user(value, (__u32 *) arg); +- break; +- +- case LIRC_SET_SEND_MODE: +- case LIRC_SET_REC_MODE: +- retval = get_user(value, (__u32 *) arg); +- break; +- +- case LIRC_SET_SEND_CARRIER: +- retval = get_user(value, (__u32 *) arg); +- if (retval) +- return retval; +- value /= 1000; +- if (value > IT87_CIR_FREQ_MAX || +- value < IT87_CIR_FREQ_MIN) +- return -EINVAL; +- +- it87_freq = value; +- +- spin_lock_irqsave(&hardware_lock, hw_flags); +- outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | +- (it87_freq - IT87_CIR_FREQ_MIN) << 3), +- io + IT87_CIR_TCR2); +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- dprintk("demodulation frequency: %d kHz\n", it87_freq); +- +- break; +- +- default: +- retval = -EINVAL; +- } +- +- if (retval) +- return retval; +- +- if (cmd == LIRC_SET_REC_MODE) { +- if (value != LIRC_MODE_MODE2) +- retval = -ENOSYS; +- } else if (cmd == LIRC_SET_SEND_MODE) { +- if (value != LIRC_MODE_PULSE) +- retval = -ENOSYS; +- } +- return retval; +-} +- +-static void add_read_queue(int flag, unsigned long val) +-{ +- unsigned int new_rx_tail; +- int newval; +- +- dprintk("add flag %d with val %lu\n", flag, val); +- +- newval = val & PULSE_MASK; +- +- /* +- * statistically, pulses are ~TIME_CONST/2 too long. we could +- * maybe make this more exact, but this is good enough +- */ +- if (flag) { +- /* pulse */ +- if (newval > TIME_CONST / 2) +- newval -= TIME_CONST / 2; +- else /* should not ever happen */ +- newval = 1; +- newval |= PULSE_BIT; +- } else +- newval += TIME_CONST / 2; +- new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); +- if (new_rx_tail == rx_head) { +- dprintk("Buffer overrun.\n"); +- return; +- } +- rx_buf[rx_tail] = newval; +- rx_tail = new_rx_tail; +- wake_up_interruptible(&lirc_read_queue); +-} +- +- +-static const struct file_operations lirc_fops = { +- .owner = THIS_MODULE, +- .read = lirc_read, +- .write = lirc_write, +- .poll = lirc_poll, +- .unlocked_ioctl = lirc_ioctl, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = lirc_ioctl, +-#endif +- .open = lirc_open, +- .release = lirc_close, +- .llseek = noop_llseek, +-}; +- +-static int set_use_inc(void *data) +-{ +- return 0; +-} +- +-static void set_use_dec(void *data) +-{ +-} +- +-static struct lirc_driver driver = { +- .name = LIRC_DRIVER_NAME, +- .minor = -1, +- .code_length = 1, +- .sample_rate = 0, +- .data = NULL, +- .add_to_buf = NULL, +- .set_use_inc = set_use_inc, +- .set_use_dec = set_use_dec, +- .fops = &lirc_fops, +- .dev = NULL, +- .owner = THIS_MODULE, +-}; +- +- +-static int init_chrdev(void) +-{ +- driver.minor = lirc_register_driver(&driver); +- +- if (driver.minor < 0) { +- printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); +- return -EIO; +- } +- return 0; +-} +- +- +-static void drop_chrdev(void) +-{ +- lirc_unregister_driver(driver.minor); +-} +- +- +-/* SECTION: Hardware */ +-static long delta(struct timeval *tv1, struct timeval *tv2) +-{ +- unsigned long deltv; +- +- deltv = tv2->tv_sec - tv1->tv_sec; +- if (deltv > 15) +- deltv = 0xFFFFFF; +- else +- deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; +- return deltv; +-} +- +-static void it87_timeout(unsigned long data) +-{ +- unsigned long flags; +- +- /* avoid interference with interrupt */ +- spin_lock_irqsave(&timer_lock, flags); +- +- if (digimatrix) { +- /* We have timed out. Disable the RX mechanism. */ +- +- outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | +- IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); +- if (it87_RXEN_mask) +- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- dprintk(" TIMEOUT\n"); +- timer_enabled = 0; +- +- /* fifo clear */ +- outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, +- io+IT87_CIR_TCR1); +- +- } else { +- /* +- * if last received signal was a pulse, but receiving stopped +- * within the 9 bit frame, we need to finish this pulse and +- * simulate a signal change to from pulse to space. Otherwise +- * upper layers will receive two sequences next time. +- */ +- +- if (last_value) { +- unsigned long pulse_end; +- +- /* determine 'virtual' pulse end: */ +- pulse_end = delta(&last_tv, &last_intr_tv); +- dprintk("timeout add %d for %lu usec\n", +- last_value, pulse_end); +- add_read_queue(last_value, pulse_end); +- last_value = 0; +- last_tv = last_intr_tv; +- } +- } +- spin_unlock_irqrestore(&timer_lock, flags); +-} +- +-static irqreturn_t it87_interrupt(int irq, void *dev_id) +-{ +- unsigned char data; +- struct timeval curr_tv; +- static unsigned long deltv; +- unsigned long deltintrtv; +- unsigned long flags, hw_flags; +- int iir, lsr; +- int fifo = 0; +- static char lastbit; +- char bit; +- +- /* Bit duration in microseconds */ +- const unsigned long bit_duration = 1000000ul / +- (115200 / IT87_CIR_BAUDRATE_DIVISOR); +- +- +- iir = inb(io + IT87_CIR_IIR); +- +- switch (iir & IT87_CIR_IIR_IID) { +- case 0x4: +- case 0x6: +- lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | +- IT87_CIR_RSR_RXFBC); +- fifo = lsr & IT87_CIR_RSR_RXFBC; +- dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); +- +- /* avoid interference with timer */ +- spin_lock_irqsave(&timer_lock, flags); +- spin_lock_irqsave(&hardware_lock, hw_flags); +- if (digimatrix) { +- static unsigned long acc_pulse; +- static unsigned long acc_space; +- +- do { +- data = inb(io + IT87_CIR_DR); +- data = ~data; +- fifo--; +- if (data != 0x00) { +- if (timer_enabled) +- del_timer(&timerlist); +- /* +- * start timer for end of +- * sequence detection +- */ +- timerlist.expires = jiffies + +- IT87_TIMEOUT; +- add_timer(&timerlist); +- timer_enabled = 1; +- } +- /* Loop through */ +- for (bit = 0; bit < 8; ++bit) { +- if ((data >> bit) & 1) { +- ++acc_pulse; +- if (lastbit == 0) { +- add_read_queue(0, +- acc_space * +- bit_duration); +- acc_space = 0; +- } +- } else { +- ++acc_space; +- if (lastbit == 1) { +- add_read_queue(1, +- acc_pulse * +- bit_duration); +- acc_pulse = 0; +- } +- } +- lastbit = (data >> bit) & 1; +- } +- +- } while (fifo != 0); +- } else { /* Normal Operation */ +- do { +- del_timer(&timerlist); +- data = inb(io + IT87_CIR_DR); +- +- dprintk("data=%02x\n", data); +- do_gettimeofday(&curr_tv); +- deltv = delta(&last_tv, &curr_tv); +- deltintrtv = delta(&last_intr_tv, &curr_tv); +- +- dprintk("t %lu , d %d\n", +- deltintrtv, (int)data); +- +- /* +- * if nothing came in last 2 cycles, +- * it was gap +- */ +- if (deltintrtv > TIME_CONST * 2) { +- if (last_value) { +- dprintk("GAP\n"); +- +- /* simulate signal change */ +- add_read_queue(last_value, +- deltv - +- deltintrtv); +- last_value = 0; +- last_tv.tv_sec = +- last_intr_tv.tv_sec; +- last_tv.tv_usec = +- last_intr_tv.tv_usec; +- deltv = deltintrtv; +- } +- } +- data = 1; +- if (data ^ last_value) { +- /* +- * deltintrtv > 2*TIME_CONST, +- * remember ? the other case is +- * timeout +- */ +- add_read_queue(last_value, +- deltv-TIME_CONST); +- last_value = data; +- last_tv = curr_tv; +- if (last_tv.tv_usec >= TIME_CONST) +- last_tv.tv_usec -= TIME_CONST; +- else { +- last_tv.tv_sec--; +- last_tv.tv_usec += 1000000 - +- TIME_CONST; +- } +- } +- last_intr_tv = curr_tv; +- if (data) { +- /* +- * start timer for end of +- * sequence detection +- */ +- timerlist.expires = +- jiffies + IT87_TIMEOUT; +- add_timer(&timerlist); +- } +- outb((inb(io + IT87_CIR_RCR) & +- ~IT87_CIR_RCR_RXEN) | +- IT87_CIR_RCR_RXACT, +- io + IT87_CIR_RCR); +- if (it87_RXEN_mask) +- outb(inb(io + IT87_CIR_RCR) | +- IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- fifo--; +- } while (fifo != 0); +- } +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- spin_unlock_irqrestore(&timer_lock, flags); +- +- return IRQ_RETVAL(IRQ_HANDLED); +- +- default: +- /* not our irq */ +- dprintk("unknown IRQ (shouldn't happen) !!\n"); +- return IRQ_RETVAL(IRQ_NONE); +- } +-} +- +- +-static void send_it87(unsigned long len, unsigned long stime, +- unsigned char send_byte, unsigned int count_bits) +-{ +- long count = len / stime; +- long time_left = 0; +- static unsigned char byte_out; +- unsigned long hw_flags; +- +- dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte); +- +- time_left = (long)len - (long)count * (long)stime; +- count += ((2 * time_left) / stime); +- while (count) { +- long i = 0; +- for (i = 0; i < count_bits; i++) { +- byte_out = (byte_out << 1) | (send_byte & 1); +- it87_bits_in_byte_out++; +- } +- if (it87_bits_in_byte_out == 8) { +- dprintk("out=0x%x, tsr_txfbc: 0x%x\n", +- byte_out, +- inb(io + IT87_CIR_TSR) & +- IT87_CIR_TSR_TXFBC); +- +- while ((inb(io + IT87_CIR_TSR) & +- IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) +- ; +- +- spin_lock_irqsave(&hardware_lock, hw_flags); +- outb(byte_out, io + IT87_CIR_DR); +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- +- it87_bits_in_byte_out = 0; +- it87_send_counter++; +- byte_out = 0; +- } +- count--; +- } +-} +- +- +-/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */ +- +-static void send_space(unsigned long len) +-{ +- send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); +-} +- +-static void send_pulse(unsigned long len) +-{ +- send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); +-} +- +- +-static void init_send() +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&hardware_lock, flags); +- /* RXEN=0: receiver disable */ +- it87_RXEN_mask = 0; +- outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- spin_unlock_irqrestore(&hardware_lock, flags); +- it87_bits_in_byte_out = 0; +- it87_send_counter = 0; +-} +- +- +-static void terminate_send(unsigned long len) +-{ +- unsigned long flags; +- unsigned long last = 0; +- +- last = it87_send_counter; +- /* make sure all necessary data has been sent */ +- while (last == it87_send_counter) +- send_space(len); +- /* wait until all data sent */ +- while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0) +- ; +- /* then re-enable receiver */ +- spin_lock_irqsave(&hardware_lock, flags); +- it87_RXEN_mask = IT87_CIR_RCR_RXEN; +- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, +- io + IT87_CIR_RCR); +- spin_unlock_irqrestore(&hardware_lock, flags); +-} +- +- +-static int init_hardware(void) +-{ +- unsigned long flags; +- unsigned char it87_rcr = 0; +- +- spin_lock_irqsave(&hardware_lock, flags); +- /* init cir-port */ +- /* enable r/w-access to Baudrate-Register */ +- outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); +- outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); +- outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); +- /* Baudrate Register off, define IRQs: Input only */ +- if (digimatrix) { +- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); +- /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ +- } else { +- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); +- /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ +- } +- it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; +- if (it87_enable_demodulator) +- it87_rcr |= IT87_CIR_RCR_RXEND; +- outb(it87_rcr, io + IT87_CIR_RCR); +- if (digimatrix) { +- /* Set FIFO depth to 1 byte, and disable TX */ +- outb(inb(io + IT87_CIR_TCR1) | 0x00, +- io + IT87_CIR_TCR1); +- +- /* +- * TX: it87_freq (36kHz), 'reserved' sensitivity +- * setting (0x00) +- */ +- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, +- io + IT87_CIR_TCR2); +- } else { +- /* TX: 38kHz, 13,3us (pulse-width) */ +- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, +- io + IT87_CIR_TCR2); +- } +- spin_unlock_irqrestore(&hardware_lock, flags); +- return 0; +-} +- +- +-static void drop_hardware(void) +-{ +- unsigned long flags; +- +- spin_lock_irqsave(&hardware_lock, flags); +- disable_irq(irq); +- /* receiver disable */ +- it87_RXEN_mask = 0; +- outb(0x1, io + IT87_CIR_RCR); +- /* turn off irqs */ +- outb(0, io + IT87_CIR_IER); +- /* fifo clear */ +- outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); +- /* reset */ +- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); +- enable_irq(irq); +- spin_unlock_irqrestore(&hardware_lock, flags); +-} +- +- +-static unsigned char it87_read(unsigned char port) +-{ +- outb(port, IT87_ADRPORT); +- return inb(IT87_DATAPORT); +-} +- +- +-static void it87_write(unsigned char port, unsigned char data) +-{ +- outb(port, IT87_ADRPORT); +- outb(data, IT87_DATAPORT); +-} +- +- +-/* SECTION: Initialisation */ +- +-static int init_port(void) +-{ +- unsigned long hw_flags; +- int retval = 0; +- +- unsigned char init_bytes[4] = IT87_INIT; +- unsigned char it87_chipid = 0; +- unsigned char ldn = 0; +- unsigned int it87_io = 0; +- unsigned int it87_irq = 0; +- +- /* Enter MB PnP Mode */ +- outb(init_bytes[0], IT87_ADRPORT); +- outb(init_bytes[1], IT87_ADRPORT); +- outb(init_bytes[2], IT87_ADRPORT); +- outb(init_bytes[3], IT87_ADRPORT); +- +- /* 8712 or 8705 ? */ +- it87_chipid = it87_read(IT87_CHIP_ID1); +- if (it87_chipid != 0x87) { +- retval = -ENXIO; +- return retval; +- } +- it87_chipid = it87_read(IT87_CHIP_ID2); +- if ((it87_chipid != 0x05) && +- (it87_chipid != 0x12) && +- (it87_chipid != 0x18) && +- (it87_chipid != 0x20)) { +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": no IT8704/05/12/18/20 found (claimed IT87%02x), " +- "exiting..\n", it87_chipid); +- retval = -ENXIO; +- return retval; +- } +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": found IT87%02x.\n", +- it87_chipid); +- +- /* get I/O-Port and IRQ */ +- if (it87_chipid == 0x12 || it87_chipid == 0x18) +- ldn = IT8712_CIR_LDN; +- else +- ldn = IT8705_CIR_LDN; +- it87_write(IT87_LDN, ldn); +- +- it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + +- it87_read(IT87_CIR_BASE_LSB); +- if (it87_io == 0) { +- if (io == 0) +- io = IT87_CIR_DEFAULT_IOBASE; +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": set default io 0x%x\n", +- io); +- it87_write(IT87_CIR_BASE_MSB, io / 0x100); +- it87_write(IT87_CIR_BASE_LSB, io % 0x100); +- } else +- io = it87_io; +- +- it87_irq = it87_read(IT87_CIR_IRQ); +- if (digimatrix || it87_irq == 0) { +- if (irq == 0) +- irq = IT87_CIR_DEFAULT_IRQ; +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": set default irq 0x%x\n", +- irq); +- it87_write(IT87_CIR_IRQ, irq); +- } else +- irq = it87_irq; +- +- spin_lock_irqsave(&hardware_lock, hw_flags); +- /* reset */ +- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); +- /* fifo clear */ +- outb(IT87_CIR_TCR1_FIFOCLR | +- /* IT87_CIR_TCR1_ILE | */ +- IT87_CIR_TCR1_TXRLE | +- IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); +- spin_unlock_irqrestore(&hardware_lock, hw_flags); +- +- /* get I/O port access and IRQ line */ +- if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { +- printk(KERN_ERR LIRC_DRIVER_NAME +- ": i/o port 0x%.4x already in use.\n", io); +- /* Leaving MB PnP Mode */ +- it87_write(IT87_CFGCTRL, 0x2); +- return -EBUSY; +- } +- +- /* activate CIR-Device */ +- it87_write(IT87_CIR_ACT, 0x1); +- +- /* Leaving MB PnP Mode */ +- it87_write(IT87_CFGCTRL, 0x2); +- +- retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, +- LIRC_DRIVER_NAME, NULL); +- if (retval < 0) { +- printk(KERN_ERR LIRC_DRIVER_NAME +- ": IRQ %d already in use.\n", +- irq); +- release_region(io, 8); +- return retval; +- } +- +- printk(KERN_INFO LIRC_DRIVER_NAME +- ": I/O port 0x%.4x, IRQ %d.\n", io, irq); +- +- init_timer(&timerlist); +- timerlist.function = it87_timeout; +- timerlist.data = 0xabadcafe; +- +- return 0; +-} +- +- +-static void drop_port(void) +-{ +-#if 0 +- unsigned char init_bytes[4] = IT87_INIT; +- +- /* Enter MB PnP Mode */ +- outb(init_bytes[0], IT87_ADRPORT); +- outb(init_bytes[1], IT87_ADRPORT); +- outb(init_bytes[2], IT87_ADRPORT); +- outb(init_bytes[3], IT87_ADRPORT); +- +- /* deactivate CIR-Device */ +- it87_write(IT87_CIR_ACT, 0x0); +- +- /* Leaving MB PnP Mode */ +- it87_write(IT87_CFGCTRL, 0x2); +-#endif +- +- del_timer_sync(&timerlist); +- free_irq(irq, NULL); +- release_region(io, 8); +-} +- +- +-static int init_lirc_it87(void) +-{ +- int retval; +- +- init_waitqueue_head(&lirc_read_queue); +- retval = init_port(); +- if (retval < 0) +- return retval; +- init_hardware(); +- printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); +- return 0; +-} +- +-static int it87_probe(struct pnp_dev *pnp_dev, +- const struct pnp_device_id *dev_id) +-{ +- int retval; +- +- driver.dev = &pnp_dev->dev; +- +- retval = init_chrdev(); +- if (retval < 0) +- return retval; +- +- retval = init_lirc_it87(); +- if (retval) +- goto init_lirc_it87_failed; +- +- return 0; +- +-init_lirc_it87_failed: +- drop_chrdev(); +- +- return retval; +-} +- +-static int __init lirc_it87_init(void) +-{ +- return pnp_register_driver(&it87_pnp_driver); +-} +- +- +-static void __exit lirc_it87_exit(void) +-{ +- drop_hardware(); +- drop_chrdev(); +- drop_port(); +- pnp_unregister_driver(&it87_pnp_driver); +- printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); +-} +- +-/* SECTION: PNP for ITE8704/13/18 */ +- +-static const struct pnp_device_id pnp_dev_table[] = { +- {"ITE8704", 0}, +- {"ITE8713", 0}, +- {} +-}; +- +-MODULE_DEVICE_TABLE(pnp, pnp_dev_table); +- +-static struct pnp_driver it87_pnp_driver = { +- .name = LIRC_DRIVER_NAME, +- .id_table = pnp_dev_table, +- .probe = it87_probe, +-}; +- +-module_init(lirc_it87_init); +-module_exit(lirc_it87_exit); +- +-MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port"); +-MODULE_AUTHOR("Hans-Gunter Lutke Uphues"); +-MODULE_LICENSE("GPL"); +- +-module_param(io, int, S_IRUGO); +-MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); +- +-module_param(irq, int, S_IRUGO); +-#ifdef LIRC_IT87_DIGIMATRIX +-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); +-#else +-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); +-#endif +- +-module_param(it87_enable_demodulator, bool, S_IRUGO); +-MODULE_PARM_DESC(it87_enable_demodulator, +- "Receiver demodulator enable/disable (1/0), default: 0"); +- +-module_param(debug, bool, S_IRUGO | S_IWUSR); +-MODULE_PARM_DESC(debug, "Enable debugging messages"); +- +-module_param(digimatrix, bool, S_IRUGO | S_IWUSR); +-#ifdef LIRC_IT87_DIGIMATRIX +-MODULE_PARM_DESC(digimatrix, +- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); +-#else +-MODULE_PARM_DESC(digimatrix, +- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); +-#endif +- +- +-module_param(it87_freq, int, S_IRUGO); +-#ifdef LIRC_IT87_DIGIMATRIX +-MODULE_PARM_DESC(it87_freq, +- "Carrier demodulator frequency (kHz), (default: 36)"); +-#else +-MODULE_PARM_DESC(it87_freq, +- "Carrier demodulator frequency (kHz), (default: 38)"); +-#endif +diff --git a/drivers/staging/lirc/lirc_it87.h b/drivers/staging/lirc/lirc_it87.h +deleted file mode 100644 +index cf021c8..0000000 +--- a/drivers/staging/lirc/lirc_it87.h ++++ /dev/null +@@ -1,116 +0,0 @@ +-/* lirc_it87.h */ +-/* SECTION: Definitions */ +- +-/********************************* ITE IT87xx ************************/ +- +-/* based on the following documentation from ITE: +- a) IT8712F Preliminary CIR Programming Guide V0.1 +- b) IT8705F Simple LPC I/O Preliminary Specification V0.3 +- c) IT8712F EC-LPC I/O Preliminary Specification V0.5 +-*/ +- +-/* IT8712/05 Ports: */ +-#define IT87_ADRPORT 0x2e +-#define IT87_DATAPORT 0x2f +-#define IT87_INIT {0x87, 0x01, 0x55, 0x55} +- +-/* alternate Ports: */ +-/* +-#define IT87_ADRPORT 0x4e +-#define IT87_DATAPORT 0x4f +-#define IT87_INIT {0x87, 0x01, 0x55, 0xaa} +- */ +- +-/* IT8712/05 Registers */ +-#define IT87_CFGCTRL 0x2 +-#define IT87_LDN 0x7 +-#define IT87_CHIP_ID1 0x20 +-#define IT87_CHIP_ID2 0x21 +-#define IT87_CFG_VERSION 0x22 +-#define IT87_SWSUSPEND 0x23 +- +-#define IT8712_CIR_LDN 0xa +-#define IT8705_CIR_LDN 0x7 +- +-/* CIR Configuration Registers: */ +-#define IT87_CIR_ACT 0x30 +-#define IT87_CIR_BASE_MSB 0x60 +-#define IT87_CIR_BASE_LSB 0x61 +-#define IT87_CIR_IRQ 0x70 +-#define IT87_CIR_CONFIG 0xf0 +- +-/* List of IT87_CIR registers: offset to BaseAddr */ +-#define IT87_CIR_DR 0 +-#define IT87_CIR_IER 1 +-#define IT87_CIR_RCR 2 +-#define IT87_CIR_TCR1 3 +-#define IT87_CIR_TCR2 4 +-#define IT87_CIR_TSR 5 +-#define IT87_CIR_RSR 6 +-#define IT87_CIR_BDLR 5 +-#define IT87_CIR_BDHR 6 +-#define IT87_CIR_IIR 7 +- +-/* Bit Definition */ +-/* IER: */ +-#define IT87_CIR_IER_TM_EN 0x80 +-#define IT87_CIR_IER_RESEVED 0x40 +-#define IT87_CIR_IER_RESET 0x20 +-#define IT87_CIR_IER_BR 0x10 +-#define IT87_CIR_IER_IEC 0x8 +-#define IT87_CIR_IER_RFOIE 0x4 +-#define IT87_CIR_IER_RDAIE 0x2 +-#define IT87_CIR_IER_TLDLIE 0x1 +- +-/* RCR: */ +-#define IT87_CIR_RCR_RDWOS 0x80 +-#define IT87_CIR_RCR_HCFS 0x40 +-#define IT87_CIR_RCR_RXEN 0x20 +-#define IT87_CIR_RCR_RXEND 0x10 +-#define IT87_CIR_RCR_RXACT 0x8 +-#define IT87_CIR_RCR_RXDCR 0x7 +- +-/* TCR1: */ +-#define IT87_CIR_TCR1_FIFOCLR 0x80 +-#define IT87_CIR_TCR1_ILE 0x40 +-#define IT87_CIR_TCR1_FIFOTL 0x30 +-#define IT87_CIR_TCR1_TXRLE 0x8 +-#define IT87_CIR_TCR1_TXENDF 0x4 +-#define IT87_CIR_TCR1_TXMPM 0x3 +- +-/* TCR2: */ +-#define IT87_CIR_TCR2_CFQ 0xf8 +-#define IT87_CIR_TCR2_TXMPW 0x7 +- +-/* TSR: */ +-#define IT87_CIR_TSR_RESERVED 0xc0 +-#define IT87_CIR_TSR_TXFBC 0x3f +- +-/* RSR: */ +-#define IT87_CIR_RSR_RXFTO 0x80 +-#define IT87_CIR_RSR_RESERVED 0x40 +-#define IT87_CIR_RSR_RXFBC 0x3f +- +-/* IIR: */ +-#define IT87_CIR_IIR_RESERVED 0xf8 +-#define IT87_CIR_IIR_IID 0x6 +-#define IT87_CIR_IIR_IIP 0x1 +- +-/* TM: */ +-#define IT87_CIR_TM_IL_SEL 0x80 +-#define IT87_CIR_TM_RESERVED 0x40 +-#define IT87_CIR_TM_TM_REG 0x3f +- +-#define IT87_CIR_FIFO_SIZE 32 +- +-/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ +-#define IT87_CIR_BAUDRATE_DIVISOR 0x1 +-#define IT87_CIR_DEFAULT_IOBASE 0x310 +-#define IT87_CIR_DEFAULT_IRQ 0x7 +-#define IT87_CIR_SPACE 0x00 +-#define IT87_CIR_PULSE 0xff +-#define IT87_CIR_FREQ_MIN 27 +-#define IT87_CIR_FREQ_MAX 58 +-#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) +- +-/********************************* ITE IT87xx ************************/ +diff --git a/drivers/staging/lirc/lirc_ite8709.c b/drivers/staging/lirc/lirc_ite8709.c +deleted file mode 100644 +index cb20cfd..0000000 +--- a/drivers/staging/lirc/lirc_ite8709.c ++++ /dev/null +@@ -1,542 +0,0 @@ +-/* +- * LIRC driver for ITE8709 CIR port +- * +- * Copyright (C) 2008 Grégory Lardière +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License as +- * published by the Free Software Foundation; either version 2 of the +- * License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +- * USA +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#define LIRC_DRIVER_NAME "lirc_ite8709" +- +-#define BUF_CHUNK_SIZE sizeof(int) +-#define BUF_SIZE (128*BUF_CHUNK_SIZE) +- +-/* +- * The ITE8709 device seems to be the combination of IT8512 superIO chip and +- * a specific firmware running on the IT8512's embedded micro-controller. +- * In addition of the embedded micro-controller, the IT8512 chip contains a +- * CIR module and several other modules. A few modules are directly accessible +- * by the host CPU, but most of them are only accessible by the +- * micro-controller. The CIR module is only accessible by the micro-controller. +- * The battery-backed SRAM module is accessible by the host CPU and the +- * micro-controller. So one of the MC's firmware role is to act as a bridge +- * between the host CPU and the CIR module. The firmware implements a kind of +- * communication protocol using the SRAM module as a shared memory. The IT8512 +- * specification is publicly available on ITE's web site, but the communication +- * protocol is not, so it was reverse-engineered. +- */ +- +-/* ITE8709 Registers addresses and values (reverse-engineered) */ +-#define ITE8709_MODE 0x1a +-#define ITE8709_REG_ADR 0x1b +-#define ITE8709_REG_VAL 0x1c +-#define ITE8709_IIR 0x1e /* Interrupt identification register */ +-#define ITE8709_RFSR 0x1f /* Receiver FIFO status register */ +-#define ITE8709_FIFO_START 0x20 +- +-#define ITE8709_MODE_READY 0X00 +-#define ITE8709_MODE_WRITE 0X01 +-#define ITE8709_MODE_READ 0X02 +-#define ITE8709_IIR_RDAI 0x02 /* Receiver data available interrupt */ +-#define ITE8709_IIR_RFOI 0x04 /* Receiver FIFO overrun interrupt */ +-#define ITE8709_RFSR_MASK 0x3f /* FIFO byte count mask */ +- +-/* +- * IT8512 CIR-module registers addresses and values +- * (from IT8512 E/F specification v0.4.1) +- */ +-#define IT8512_REG_MSTCR 0x01 /* Master control register */ +-#define IT8512_REG_IER 0x02 /* Interrupt enable register */ +-#define IT8512_REG_CFR 0x04 /* Carrier frequency register */ +-#define IT8512_REG_RCR 0x05 /* Receive control register */ +-#define IT8512_REG_BDLR 0x08 /* Baud rate divisor low byte register */ +-#define IT8512_REG_BDHR 0x09 /* Baud rate divisor high byte register */ +- +-#define IT8512_MSTCR_RESET 0x01 /* Reset registers to default value */ +-#define IT8512_MSTCR_FIFOCLR 0x02 /* Clear FIFO */ +-#define IT8512_MSTCR_FIFOTL_7 0x04 /* FIFO threshold level : 7 */ +-#define IT8512_MSTCR_FIFOTL_25 0x0c /* FIFO threshold level : 25 */ +-#define IT8512_IER_RDAIE 0x02 /* Enable data interrupt request */ +-#define IT8512_IER_RFOIE 0x04 /* Enable FIFO overrun interrupt req */ +-#define IT8512_IER_IEC 0x80 /* Enable interrupt request */ +-#define IT8512_CFR_CF_36KHZ 0x09 /* Carrier freq : low speed, 36kHz */ +-#define IT8512_RCR_RXDCR_1 0x01 /* Demodulation carrier range : 1 */ +-#define IT8512_RCR_RXACT 0x08 /* Receiver active */ +-#define IT8512_RCR_RXEN 0x80 /* Receiver enable */ +-#define IT8512_BDR_6 6 /* Baud rate divisor : 6 */ +- +-/* Actual values used by this driver */ +-#define CFG_FIFOTL IT8512_MSTCR_FIFOTL_25 +-#define CFG_CR_FREQ IT8512_CFR_CF_36KHZ +-#define CFG_DCR IT8512_RCR_RXDCR_1 +-#define CFG_BDR IT8512_BDR_6 +-#define CFG_TIMEOUT 100000 /* Rearm interrupt when a space is > 100 ms */ +- +-static int debug; +- +-struct ite8709_device { +- int use_count; +- int io; +- int irq; +- spinlock_t hardware_lock; +- __u64 acc_pulse; +- __u64 acc_space; +- char lastbit; +- struct timeval last_tv; +- struct lirc_driver driver; +- struct tasklet_struct tasklet; +- char force_rearm; +- char rearmed; +- char device_busy; +-}; +- +-#define dprintk(fmt, args...) \ +- do { \ +- if (debug) \ +- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ +- fmt, ## args); \ +- } while (0) +- +- +-static unsigned char ite8709_read(struct ite8709_device *dev, +- unsigned char port) +-{ +- outb(port, dev->io); +- return inb(dev->io+1); +-} +- +-static void ite8709_write(struct ite8709_device *dev, unsigned char port, +- unsigned char data) +-{ +- outb(port, dev->io); +- outb(data, dev->io+1); +-} +- +-static void ite8709_wait_device(struct ite8709_device *dev) +-{ +- int i = 0; +- /* +- * loop until device tells it's ready to continue +- * iterations count is usually ~750 but can sometimes achieve 13000 +- */ +- for (i = 0; i < 15000; i++) { +- udelay(2); +- if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY) +- break; +- } +-} +- +-static void ite8709_write_register(struct ite8709_device *dev, +- unsigned char reg_adr, unsigned char reg_value) +-{ +- ite8709_wait_device(dev); +- +- ite8709_write(dev, ITE8709_REG_VAL, reg_value); +- ite8709_write(dev, ITE8709_REG_ADR, reg_adr); +- ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE); +-} +- +-static void ite8709_init_hardware(struct ite8709_device *dev) +-{ +- spin_lock_irq(&dev->hardware_lock); +- dev->device_busy = 1; +- spin_unlock_irq(&dev->hardware_lock); +- +- ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff); +- ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff); +- ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ); +- ite8709_write_register(dev, IT8512_REG_IER, +- IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE); +- ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR); +- ite8709_write_register(dev, IT8512_REG_MSTCR, +- CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); +- ite8709_write_register(dev, IT8512_REG_RCR, +- IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); +- +- spin_lock_irq(&dev->hardware_lock); +- dev->device_busy = 0; +- spin_unlock_irq(&dev->hardware_lock); +- +- tasklet_enable(&dev->tasklet); +-} +- +-static void ite8709_drop_hardware(struct ite8709_device *dev) +-{ +- tasklet_disable(&dev->tasklet); +- +- spin_lock_irq(&dev->hardware_lock); +- dev->device_busy = 1; +- spin_unlock_irq(&dev->hardware_lock); +- +- ite8709_write_register(dev, IT8512_REG_RCR, 0); +- ite8709_write_register(dev, IT8512_REG_MSTCR, +- IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR); +- +- spin_lock_irq(&dev->hardware_lock); +- dev->device_busy = 0; +- spin_unlock_irq(&dev->hardware_lock); +-} +- +-static int ite8709_set_use_inc(void *data) +-{ +- struct ite8709_device *dev; +- dev = data; +- if (dev->use_count == 0) +- ite8709_init_hardware(dev); +- dev->use_count++; +- return 0; +-} +- +-static void ite8709_set_use_dec(void *data) +-{ +- struct ite8709_device *dev; +- dev = data; +- dev->use_count--; +- if (dev->use_count == 0) +- ite8709_drop_hardware(dev); +-} +- +-static void ite8709_add_read_queue(struct ite8709_device *dev, int flag, +- __u64 val) +-{ +- int value; +- +- dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space"); +- +- value = (val > PULSE_MASK) ? PULSE_MASK : val; +- if (flag) +- value |= PULSE_BIT; +- +- if (!lirc_buffer_full(dev->driver.rbuf)) { +- lirc_buffer_write(dev->driver.rbuf, (void *) &value); +- wake_up(&dev->driver.rbuf->wait_poll); +- } +-} +- +-static irqreturn_t ite8709_interrupt(int irq, void *dev_id) +-{ +- unsigned char data; +- int iir, rfsr, i; +- int fifo = 0; +- char bit; +- struct timeval curr_tv; +- +- /* Bit duration in microseconds */ +- const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR); +- +- struct ite8709_device *dev; +- dev = dev_id; +- +- /* +- * If device is busy, we simply discard data because we are in one of +- * these two cases : shutting down or rearming the device, so this +- * doesn't really matter and this avoids waiting too long in IRQ ctx +- */ +- spin_lock(&dev->hardware_lock); +- if (dev->device_busy) { +- spin_unlock(&dev->hardware_lock); +- return IRQ_RETVAL(IRQ_HANDLED); +- } +- +- iir = ite8709_read(dev, ITE8709_IIR); +- +- switch (iir) { +- case ITE8709_IIR_RFOI: +- dprintk("fifo overrun, scheduling forced rearm just in case\n"); +- dev->force_rearm = 1; +- tasklet_schedule(&dev->tasklet); +- spin_unlock(&dev->hardware_lock); +- return IRQ_RETVAL(IRQ_HANDLED); +- +- case ITE8709_IIR_RDAI: +- rfsr = ite8709_read(dev, ITE8709_RFSR); +- fifo = rfsr & ITE8709_RFSR_MASK; +- if (fifo > 32) +- fifo = 32; +- dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo); +- +- if (dev->rearmed) { +- do_gettimeofday(&curr_tv); +- dev->acc_space += 1000000ull +- * (curr_tv.tv_sec - dev->last_tv.tv_sec) +- + (curr_tv.tv_usec - dev->last_tv.tv_usec); +- dev->rearmed = 0; +- } +- for (i = 0; i < fifo; i++) { +- data = ite8709_read(dev, i+ITE8709_FIFO_START); +- data = ~data; +- /* Loop through */ +- for (bit = 0; bit < 8; ++bit) { +- if ((data >> bit) & 1) { +- dev->acc_pulse += bit_duration; +- if (dev->lastbit == 0) { +- ite8709_add_read_queue(dev, 0, +- dev->acc_space); +- dev->acc_space = 0; +- } +- } else { +- dev->acc_space += bit_duration; +- if (dev->lastbit == 1) { +- ite8709_add_read_queue(dev, 1, +- dev->acc_pulse); +- dev->acc_pulse = 0; +- } +- } +- dev->lastbit = (data >> bit) & 1; +- } +- } +- ite8709_write(dev, ITE8709_RFSR, 0); +- +- if (dev->acc_space > CFG_TIMEOUT) { +- dprintk("scheduling rearm IRQ\n"); +- do_gettimeofday(&dev->last_tv); +- dev->force_rearm = 0; +- tasklet_schedule(&dev->tasklet); +- } +- +- spin_unlock(&dev->hardware_lock); +- return IRQ_RETVAL(IRQ_HANDLED); +- +- default: +- /* not our irq */ +- dprintk("unknown IRQ (shouldn't happen) !!\n"); +- spin_unlock(&dev->hardware_lock); +- return IRQ_RETVAL(IRQ_NONE); +- } +-} +- +-static void ite8709_rearm_irq(unsigned long data) +-{ +- struct ite8709_device *dev; +- unsigned long flags; +- dev = (struct ite8709_device *) data; +- +- spin_lock_irqsave(&dev->hardware_lock, flags); +- dev->device_busy = 1; +- spin_unlock_irqrestore(&dev->hardware_lock, flags); +- +- if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) { +- dprintk("rearming IRQ\n"); +- ite8709_write_register(dev, IT8512_REG_RCR, +- IT8512_RCR_RXACT | CFG_DCR); +- ite8709_write_register(dev, IT8512_REG_MSTCR, +- CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); +- ite8709_write_register(dev, IT8512_REG_RCR, +- IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); +- if (!dev->force_rearm) +- dev->rearmed = 1; +- dev->force_rearm = 0; +- } +- +- spin_lock_irqsave(&dev->hardware_lock, flags); +- dev->device_busy = 0; +- spin_unlock_irqrestore(&dev->hardware_lock, flags); +-} +- +-static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno, +- char *msg) +-{ +- if (msg != NULL) +- printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg); +- +- switch (stage) { +- case 6: +- if (dev->use_count > 0) +- ite8709_drop_hardware(dev); +- case 5: +- free_irq(dev->irq, dev); +- case 4: +- release_region(dev->io, 2); +- case 3: +- lirc_unregister_driver(dev->driver.minor); +- case 2: +- lirc_buffer_free(dev->driver.rbuf); +- kfree(dev->driver.rbuf); +- case 1: +- kfree(dev); +- case 0: +- ; +- } +- +- return errno; +-} +- +-static int __devinit ite8709_pnp_probe(struct pnp_dev *dev, +- const struct pnp_device_id *dev_id) +-{ +- struct lirc_driver *driver; +- struct ite8709_device *ite8709_dev; +- int ret; +- +- /* Check resources validity */ +- if (!pnp_irq_valid(dev, 0)) +- return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ"); +- if (!pnp_port_valid(dev, 2)) +- return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port"); +- +- /* Allocate memory for device struct */ +- ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL); +- if (ite8709_dev == NULL) +- return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed"); +- pnp_set_drvdata(dev, ite8709_dev); +- +- /* Initialize device struct */ +- ite8709_dev->use_count = 0; +- ite8709_dev->irq = pnp_irq(dev, 0); +- ite8709_dev->io = pnp_port_start(dev, 2); +- ite8709_dev->hardware_lock = +- __SPIN_LOCK_UNLOCKED(ite8709_dev->hardware_lock); +- ite8709_dev->acc_pulse = 0; +- ite8709_dev->acc_space = 0; +- ite8709_dev->lastbit = 0; +- do_gettimeofday(&ite8709_dev->last_tv); +- tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq, +- (long) ite8709_dev); +- ite8709_dev->force_rearm = 0; +- ite8709_dev->rearmed = 0; +- ite8709_dev->device_busy = 0; +- +- /* Initialize driver struct */ +- driver = &ite8709_dev->driver; +- strcpy(driver->name, LIRC_DRIVER_NAME); +- driver->minor = -1; +- driver->code_length = sizeof(int) * 8; +- driver->sample_rate = 0; +- driver->features = LIRC_CAN_REC_MODE2; +- driver->data = ite8709_dev; +- driver->add_to_buf = NULL; +- driver->set_use_inc = ite8709_set_use_inc; +- driver->set_use_dec = ite8709_set_use_dec; +- driver->dev = &dev->dev; +- driver->owner = THIS_MODULE; +- +- /* Initialize LIRC buffer */ +- driver->rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); +- if (!driver->rbuf) +- return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, +- "can't allocate lirc_buffer"); +- if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) +- return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, +- "lirc_buffer_init() failed"); +- +- /* Register LIRC driver */ +- ret = lirc_register_driver(driver); +- if (ret < 0) +- return ite8709_cleanup(ite8709_dev, 2, ret, +- "lirc_register_driver() failed"); +- +- /* Reserve I/O port access */ +- if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME)) +- return ite8709_cleanup(ite8709_dev, 3, -EBUSY, +- "i/o port already in use"); +- +- /* Reserve IRQ line */ +- ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0, +- LIRC_DRIVER_NAME, ite8709_dev); +- if (ret < 0) +- return ite8709_cleanup(ite8709_dev, 4, ret, +- "IRQ already in use"); +- +- /* Initialize hardware */ +- ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */ +- +- printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n", +- ite8709_dev->irq, ite8709_dev->io); +- +- return 0; +-} +- +-static void __devexit ite8709_pnp_remove(struct pnp_dev *dev) +-{ +- struct ite8709_device *ite8709_dev; +- ite8709_dev = pnp_get_drvdata(dev); +- +- ite8709_cleanup(ite8709_dev, 6, 0, NULL); +- +- printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n"); +-} +- +-#ifdef CONFIG_PM +-static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state) +-{ +- struct ite8709_device *ite8709_dev; +- ite8709_dev = pnp_get_drvdata(dev); +- +- if (ite8709_dev->use_count > 0) +- ite8709_drop_hardware(ite8709_dev); +- +- return 0; +-} +- +-static int ite8709_pnp_resume(struct pnp_dev *dev) +-{ +- struct ite8709_device *ite8709_dev; +- ite8709_dev = pnp_get_drvdata(dev); +- +- if (ite8709_dev->use_count > 0) +- ite8709_init_hardware(ite8709_dev); +- +- return 0; +-} +-#else +-#define ite8709_pnp_suspend NULL +-#define ite8709_pnp_resume NULL +-#endif +- +-static const struct pnp_device_id pnp_dev_table[] = { +- {"ITE8709", 0}, +- {} +-}; +- +-MODULE_DEVICE_TABLE(pnp, pnp_dev_table); +- +-static struct pnp_driver ite8709_pnp_driver = { +- .name = LIRC_DRIVER_NAME, +- .probe = ite8709_pnp_probe, +- .remove = __devexit_p(ite8709_pnp_remove), +- .suspend = ite8709_pnp_suspend, +- .resume = ite8709_pnp_resume, +- .id_table = pnp_dev_table, +-}; +- +-static int __init ite8709_init_module(void) +-{ +- return pnp_register_driver(&ite8709_pnp_driver); +-} +-module_init(ite8709_init_module); +- +-static void __exit ite8709_cleanup_module(void) +-{ +- pnp_unregister_driver(&ite8709_pnp_driver); +-} +-module_exit(ite8709_cleanup_module); +- +-MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port"); +-MODULE_AUTHOR("Grégory Lardière"); +-MODULE_LICENSE("GPL"); +- +-module_param(debug, bool, S_IRUGO | S_IWUSR); +-MODULE_PARM_DESC(debug, "Enable debugging messages"); +diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c +index 925eabe..63a438d 100644 +--- a/drivers/staging/lirc/lirc_sasem.c ++++ b/drivers/staging/lirc/lirc_sasem.c +@@ -364,7 +364,7 @@ static ssize_t vfd_write(struct file *file, const char *buf, + int i; + int retval = 0; + struct sasem_context *context; +- int *data_buf; ++ int *data_buf = NULL; + + context = (struct sasem_context *) file->private_data; + if (!context) { +diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c +index 0aad0d7..dd6a57c 100644 +--- a/drivers/staging/lirc/lirc_zilog.c ++++ b/drivers/staging/lirc/lirc_zilog.c +@@ -63,14 +63,16 @@ + #include + #include + ++struct IR; ++ + struct IR_rx { ++ struct kref ref; ++ struct IR *ir; ++ + /* RX device */ ++ struct mutex client_lock; + struct i2c_client *c; + +- /* RX device buffer & lock */ +- struct lirc_buffer buf; +- struct mutex buf_lock; +- + /* RX polling thread data */ + struct task_struct *task; + +@@ -80,7 +82,11 @@ struct IR_rx { + }; + + struct IR_tx { ++ struct kref ref; ++ struct IR *ir; ++ + /* TX device */ ++ struct mutex client_lock; + struct i2c_client *c; + + /* TX additional actions needed */ +@@ -89,19 +95,34 @@ struct IR_tx { + }; + + struct IR { ++ struct kref ref; ++ struct list_head list; ++ ++ /* FIXME spinlock access to l.features */ + struct lirc_driver l; ++ struct lirc_buffer rbuf; + + struct mutex ir_lock; +- int open; ++ atomic_t open_count; + + struct i2c_adapter *adapter; ++ ++ spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */ + struct IR_rx *rx; ++ ++ spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */ + struct IR_tx *tx; + }; + +-/* Minor -> data mapping */ +-static struct mutex ir_devices_lock; +-static struct IR *ir_devices[MAX_IRCTL_DEVICES]; ++/* IR transceiver instance object list */ ++/* ++ * This lock is used for the following: ++ * a. ir_devices_list access, insertions, deletions ++ * b. struct IR kref get()s and put()s ++ * c. serialization of ir_probe() for the two i2c_clients for a Z8 ++ */ ++static DEFINE_MUTEX(ir_devices_lock); ++static LIST_HEAD(ir_devices_list); + + /* Block size for IR transmitter */ + #define TX_BLOCK_SIZE 99 +@@ -147,6 +168,157 @@ static int minor = -1; /* minor number */ + ## args); \ + } while (0) + ++ ++/* struct IR reference counting */ ++static struct IR *get_ir_device(struct IR *ir, bool ir_devices_lock_held) ++{ ++ if (ir_devices_lock_held) { ++ kref_get(&ir->ref); ++ } else { ++ mutex_lock(&ir_devices_lock); ++ kref_get(&ir->ref); ++ mutex_unlock(&ir_devices_lock); ++ } ++ return ir; ++} ++ ++static void release_ir_device(struct kref *ref) ++{ ++ struct IR *ir = container_of(ref, struct IR, ref); ++ ++ /* ++ * Things should be in this state by now: ++ * ir->rx set to NULL and deallocated - happens before ir->rx->ir put() ++ * ir->rx->task kthread stopped - happens before ir->rx->ir put() ++ * ir->tx set to NULL and deallocated - happens before ir->tx->ir put() ++ * ir->open_count == 0 - happens on final close() ++ * ir_lock, tx_ref_lock, rx_ref_lock, all released ++ */ ++ if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) { ++ lirc_unregister_driver(ir->l.minor); ++ ir->l.minor = MAX_IRCTL_DEVICES; ++ } ++ if (ir->rbuf.fifo_initialized) ++ lirc_buffer_free(&ir->rbuf); ++ list_del(&ir->list); ++ kfree(ir); ++} ++ ++static int put_ir_device(struct IR *ir, bool ir_devices_lock_held) ++{ ++ int released; ++ ++ if (ir_devices_lock_held) ++ return kref_put(&ir->ref, release_ir_device); ++ ++ mutex_lock(&ir_devices_lock); ++ released = kref_put(&ir->ref, release_ir_device); ++ mutex_unlock(&ir_devices_lock); ++ ++ return released; ++} ++ ++/* struct IR_rx reference counting */ ++static struct IR_rx *get_ir_rx(struct IR *ir) ++{ ++ struct IR_rx *rx; ++ ++ spin_lock(&ir->rx_ref_lock); ++ rx = ir->rx; ++ if (rx != NULL) ++ kref_get(&rx->ref); ++ spin_unlock(&ir->rx_ref_lock); ++ return rx; ++} ++ ++static void destroy_rx_kthread(struct IR_rx *rx, bool ir_devices_lock_held) ++{ ++ /* end up polling thread */ ++ if (!IS_ERR_OR_NULL(rx->task)) { ++ kthread_stop(rx->task); ++ rx->task = NULL; ++ /* Put the ir ptr that ir_probe() gave to the rx poll thread */ ++ put_ir_device(rx->ir, ir_devices_lock_held); ++ } ++} ++ ++static void release_ir_rx(struct kref *ref) ++{ ++ struct IR_rx *rx = container_of(ref, struct IR_rx, ref); ++ struct IR *ir = rx->ir; ++ ++ /* ++ * This release function can't do all the work, as we want ++ * to keep the rx_ref_lock a spinlock, and killing the poll thread ++ * and releasing the ir reference can cause a sleep. That work is ++ * performed by put_ir_rx() ++ */ ++ ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; ++ /* Don't put_ir_device(rx->ir) here; lock can't be freed yet */ ++ ir->rx = NULL; ++ /* Don't do the kfree(rx) here; we still need to kill the poll thread */ ++ return; ++} ++ ++static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held) ++{ ++ int released; ++ struct IR *ir = rx->ir; ++ ++ spin_lock(&ir->rx_ref_lock); ++ released = kref_put(&rx->ref, release_ir_rx); ++ spin_unlock(&ir->rx_ref_lock); ++ /* Destroy the rx kthread while not holding the spinlock */ ++ if (released) { ++ destroy_rx_kthread(rx, ir_devices_lock_held); ++ kfree(rx); ++ /* Make sure we're not still in a poll_table somewhere */ ++ wake_up_interruptible(&ir->rbuf.wait_poll); ++ } ++ /* Do a reference put() for the rx->ir reference, if we released rx */ ++ if (released) ++ put_ir_device(ir, ir_devices_lock_held); ++ return released; ++} ++ ++/* struct IR_tx reference counting */ ++static struct IR_tx *get_ir_tx(struct IR *ir) ++{ ++ struct IR_tx *tx; ++ ++ spin_lock(&ir->tx_ref_lock); ++ tx = ir->tx; ++ if (tx != NULL) ++ kref_get(&tx->ref); ++ spin_unlock(&ir->tx_ref_lock); ++ return tx; ++} ++ ++static void release_ir_tx(struct kref *ref) ++{ ++ struct IR_tx *tx = container_of(ref, struct IR_tx, ref); ++ struct IR *ir = tx->ir; ++ ++ ir->l.features &= ~LIRC_CAN_SEND_PULSE; ++ /* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */ ++ ir->tx = NULL; ++ kfree(tx); ++} ++ ++static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held) ++{ ++ int released; ++ struct IR *ir = tx->ir; ++ ++ spin_lock(&ir->tx_ref_lock); ++ released = kref_put(&tx->ref, release_ir_tx); ++ spin_unlock(&ir->tx_ref_lock); ++ /* Do a reference put() for the tx->ir reference, if we released tx */ ++ if (released) ++ put_ir_device(ir, ir_devices_lock_held); ++ return released; ++} ++ + static int add_to_buf(struct IR *ir) + { + __u16 code; +@@ -156,23 +328,38 @@ static int add_to_buf(struct IR *ir) + int ret; + int failures = 0; + unsigned char sendbuf[1] = { 0 }; +- struct IR_rx *rx = ir->rx; ++ struct lirc_buffer *rbuf = ir->l.rbuf; ++ struct IR_rx *rx; ++ struct IR_tx *tx; + ++ if (lirc_buffer_full(rbuf)) { ++ dprintk("buffer overflow\n"); ++ return -EOVERFLOW; ++ } ++ ++ rx = get_ir_rx(ir); + if (rx == NULL) + return -ENXIO; + +- if (lirc_buffer_full(&rx->buf)) { +- dprintk("buffer overflow\n"); +- return -EOVERFLOW; ++ /* Ensure our rx->c i2c_client remains valid for the duration */ ++ mutex_lock(&rx->client_lock); ++ if (rx->c == NULL) { ++ mutex_unlock(&rx->client_lock); ++ put_ir_rx(rx, false); ++ return -ENXIO; + } + ++ tx = get_ir_tx(ir); ++ + /* + * service the device as long as it is returning + * data and we have space + */ + do { +- if (kthread_should_stop()) +- return -ENODATA; ++ if (kthread_should_stop()) { ++ ret = -ENODATA; ++ break; ++ } + + /* + * Lock i2c bus for the duration. RX/TX chips interfere so +@@ -182,7 +369,8 @@ static int add_to_buf(struct IR *ir) + + if (kthread_should_stop()) { + mutex_unlock(&ir->ir_lock); +- return -ENODATA; ++ ret = -ENODATA; ++ break; + } + + /* +@@ -196,7 +384,7 @@ static int add_to_buf(struct IR *ir) + mutex_unlock(&ir->ir_lock); + zilog_error("unable to read from the IR chip " + "after 3 resets, giving up\n"); +- return ret; ++ break; + } + + /* Looks like the chip crashed, reset it */ +@@ -206,19 +394,23 @@ static int add_to_buf(struct IR *ir) + set_current_state(TASK_UNINTERRUPTIBLE); + if (kthread_should_stop()) { + mutex_unlock(&ir->ir_lock); +- return -ENODATA; ++ ret = -ENODATA; ++ break; + } + schedule_timeout((100 * HZ + 999) / 1000); +- ir->tx->need_boot = 1; ++ if (tx != NULL) ++ tx->need_boot = 1; + + ++failures; + mutex_unlock(&ir->ir_lock); ++ ret = 0; + continue; + } + + if (kthread_should_stop()) { + mutex_unlock(&ir->ir_lock); +- return -ENODATA; ++ ret = -ENODATA; ++ break; + } + ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf)); + mutex_unlock(&ir->ir_lock); +@@ -234,12 +426,17 @@ static int add_to_buf(struct IR *ir) + + /* key pressed ? */ + if (rx->hdpvr_data_fmt) { +- if (got_data && (keybuf[0] == 0x80)) +- return 0; +- else if (got_data && (keybuf[0] == 0x00)) +- return -ENODATA; +- } else if ((rx->b[0] & 0x80) == 0) +- return got_data ? 0 : -ENODATA; ++ if (got_data && (keybuf[0] == 0x80)) { ++ ret = 0; ++ break; ++ } else if (got_data && (keybuf[0] == 0x00)) { ++ ret = -ENODATA; ++ break; ++ } ++ } else if ((rx->b[0] & 0x80) == 0) { ++ ret = got_data ? 0 : -ENODATA; ++ break; ++ } + + /* look what we have */ + code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2); +@@ -248,11 +445,16 @@ static int add_to_buf(struct IR *ir) + codes[1] = code & 0xff; + + /* return it */ +- lirc_buffer_write(&rx->buf, codes); ++ lirc_buffer_write(rbuf, codes); + ++got_data; +- } while (!lirc_buffer_full(&rx->buf)); ++ ret = 0; ++ } while (!lirc_buffer_full(rbuf)); + +- return 0; ++ mutex_unlock(&rx->client_lock); ++ if (tx != NULL) ++ put_ir_tx(tx, false); ++ put_ir_rx(rx, false); ++ return ret; + } + + /* +@@ -268,19 +470,19 @@ static int add_to_buf(struct IR *ir) + static int lirc_thread(void *arg) + { + struct IR *ir = arg; +- struct IR_rx *rx = ir->rx; ++ struct lirc_buffer *rbuf = ir->l.rbuf; + + dprintk("poll thread started\n"); + + while (!kthread_should_stop()) { +- set_current_state(TASK_INTERRUPTIBLE); +- + /* if device not opened, we can sleep half a second */ +- if (!ir->open) { ++ if (atomic_read(&ir->open_count) == 0) { + schedule_timeout(HZ/2); + continue; + } + ++ set_current_state(TASK_INTERRUPTIBLE); ++ + /* + * This is ~113*2 + 24 + jitter (2*repeat gap + code length). + * We use this interval as the chip resets every time you poll +@@ -295,7 +497,7 @@ static int lirc_thread(void *arg) + if (kthread_should_stop()) + break; + if (!add_to_buf(ir)) +- wake_up_interruptible(&rx->buf.wait_poll); ++ wake_up_interruptible(&rbuf->wait_poll); + } + + dprintk("poll thread ended\n"); +@@ -304,34 +506,12 @@ static int lirc_thread(void *arg) + + static int set_use_inc(void *data) + { +- struct IR *ir = data; +- +- if (ir->l.owner == NULL || try_module_get(ir->l.owner) == 0) +- return -ENODEV; +- +- /* lock bttv in memory while /dev/lirc is in use */ +- /* +- * this is completely broken code. lirc_unregister_driver() +- * must be possible even when the device is open +- */ +- if (ir->rx != NULL) +- i2c_use_client(ir->rx->c); +- if (ir->tx != NULL) +- i2c_use_client(ir->tx->c); +- + return 0; + } + + static void set_use_dec(void *data) + { +- struct IR *ir = data; +- +- if (ir->rx) +- i2c_release_client(ir->rx->c); +- if (ir->tx) +- i2c_release_client(ir->tx->c); +- if (ir->l.owner != NULL) +- module_put(ir->l.owner); ++ return; + } + + /* safe read of a uint32 (always network byte order) */ +@@ -585,7 +765,7 @@ static int fw_load(struct IR_tx *tx) + } + + /* Request codeset data file */ +- ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &tx->c->dev); ++ ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev); + if (ret != 0) { + zilog_error("firmware haup-ir-blaster.bin not available " + "(%d)\n", ret); +@@ -711,59 +891,32 @@ out: + return ret; + } + +-/* initialise the IR TX device */ +-static int tx_init(struct IR_tx *tx) +-{ +- int ret; +- +- /* Load 'firmware' */ +- ret = fw_load(tx); +- if (ret != 0) +- return ret; +- +- /* Send boot block */ +- ret = send_boot_data(tx); +- if (ret != 0) +- return ret; +- tx->need_boot = 0; +- +- /* Looks good */ +- return 0; +-} +- +-/* do nothing stub to make LIRC happy */ +-static loff_t lseek(struct file *filep, loff_t offset, int orig) +-{ +- return -ESPIPE; +-} +- + /* copied from lirc_dev */ + static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) + { + struct IR *ir = filep->private_data; +- struct IR_rx *rx = ir->rx; +- int ret = 0, written = 0; ++ struct IR_rx *rx; ++ struct lirc_buffer *rbuf = ir->l.rbuf; ++ int ret = 0, written = 0, retries = 0; ++ unsigned int m; + DECLARE_WAITQUEUE(wait, current); + + dprintk("read called\n"); +- if (rx == NULL) +- return -ENODEV; +- +- if (mutex_lock_interruptible(&rx->buf_lock)) +- return -ERESTARTSYS; +- +- if (n % rx->buf.chunk_size) { ++ if (n % rbuf->chunk_size) { + dprintk("read result = -EINVAL\n"); +- mutex_unlock(&rx->buf_lock); + return -EINVAL; + } + ++ rx = get_ir_rx(ir); ++ if (rx == NULL) ++ return -ENXIO; ++ + /* + * we add ourselves to the task queue before buffer check + * to avoid losing scan code (in case when queue is awaken somewhere + * between while condition checking and scheduling) + */ +- add_wait_queue(&rx->buf.wait_poll, &wait); ++ add_wait_queue(&rbuf->wait_poll, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + /* +@@ -771,7 +924,7 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) + * mode and 'copy_to_user' is happy, wait for data. + */ + while (written < n && ret == 0) { +- if (lirc_buffer_empty(&rx->buf)) { ++ if (lirc_buffer_empty(rbuf)) { + /* + * According to the read(2) man page, 'written' can be + * returned as less than 'n', instead of blocking +@@ -791,20 +944,27 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } else { +- unsigned char buf[rx->buf.chunk_size]; +- lirc_buffer_read(&rx->buf, buf); +- ret = copy_to_user((void *)outbuf+written, buf, +- rx->buf.chunk_size); +- written += rx->buf.chunk_size; ++ unsigned char buf[rbuf->chunk_size]; ++ m = lirc_buffer_read(rbuf, buf); ++ if (m == rbuf->chunk_size) { ++ ret = copy_to_user((void *)outbuf+written, buf, ++ rbuf->chunk_size); ++ written += rbuf->chunk_size; ++ } else { ++ retries++; ++ } ++ if (retries >= 5) { ++ zilog_error("Buffer read failed!\n"); ++ ret = -EIO; ++ } + } + } + +- remove_wait_queue(&rx->buf.wait_poll, &wait); ++ remove_wait_queue(&rbuf->wait_poll, &wait); ++ put_ir_rx(rx, false); + set_current_state(TASK_RUNNING); +- mutex_unlock(&rx->buf_lock); + +- dprintk("read result = %s (%d)\n", +- ret ? "-EFAULT" : "OK", ret); ++ dprintk("read result = %d (%s)\n", ret, ret ? "Error" : "OK"); + + return ret ? ret : written; + } +@@ -931,17 +1091,27 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, + loff_t *ppos) + { + struct IR *ir = filep->private_data; +- struct IR_tx *tx = ir->tx; ++ struct IR_tx *tx; + size_t i; + int failures = 0; + +- if (tx == NULL) +- return -ENODEV; +- + /* Validate user parameters */ + if (n % sizeof(int)) + return -EINVAL; + ++ /* Get a struct IR_tx reference */ ++ tx = get_ir_tx(ir); ++ if (tx == NULL) ++ return -ENXIO; ++ ++ /* Ensure our tx->c i2c_client remains valid for the duration */ ++ mutex_lock(&tx->client_lock); ++ if (tx->c == NULL) { ++ mutex_unlock(&tx->client_lock); ++ put_ir_tx(tx, false); ++ return -ENXIO; ++ } ++ + /* Lock i2c bus for the duration */ + mutex_lock(&ir->ir_lock); + +@@ -952,11 +1122,24 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, + + if (copy_from_user(&command, buf + i, sizeof(command))) { + mutex_unlock(&ir->ir_lock); ++ mutex_unlock(&tx->client_lock); ++ put_ir_tx(tx, false); + return -EFAULT; + } + + /* Send boot data first if required */ + if (tx->need_boot == 1) { ++ /* Make sure we have the 'firmware' loaded, first */ ++ ret = fw_load(tx); ++ if (ret != 0) { ++ mutex_unlock(&ir->ir_lock); ++ mutex_unlock(&tx->client_lock); ++ put_ir_tx(tx, false); ++ if (ret != -ENOMEM) ++ ret = -EIO; ++ return ret; ++ } ++ /* Prep the chip for transmitting codes */ + ret = send_boot_data(tx); + if (ret == 0) + tx->need_boot = 0; +@@ -968,6 +1151,8 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, + (unsigned)command & 0xFFFF); + if (ret == -EPROTO) { + mutex_unlock(&ir->ir_lock); ++ mutex_unlock(&tx->client_lock); ++ put_ir_tx(tx, false); + return ret; + } + } +@@ -985,6 +1170,8 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, + zilog_error("unable to send to the IR chip " + "after 3 resets, giving up\n"); + mutex_unlock(&ir->ir_lock); ++ mutex_unlock(&tx->client_lock); ++ put_ir_tx(tx, false); + return ret; + } + set_current_state(TASK_UNINTERRUPTIBLE); +@@ -998,6 +1185,11 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, + /* Release i2c bus */ + mutex_unlock(&ir->ir_lock); + ++ mutex_unlock(&tx->client_lock); ++ ++ /* Give back our struct IR_tx reference */ ++ put_ir_tx(tx, false); ++ + /* All looks good */ + return n; + } +@@ -1006,23 +1198,32 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, + static unsigned int poll(struct file *filep, poll_table *wait) + { + struct IR *ir = filep->private_data; +- struct IR_rx *rx = ir->rx; ++ struct IR_rx *rx; ++ struct lirc_buffer *rbuf = ir->l.rbuf; + unsigned int ret; + + dprintk("poll called\n"); +- if (rx == NULL) +- return -ENODEV; +- +- mutex_lock(&rx->buf_lock); + +- poll_wait(filep, &rx->buf.wait_poll, wait); ++ rx = get_ir_rx(ir); ++ if (rx == NULL) { ++ /* ++ * Revisit this, if our poll function ever reports writeable ++ * status for Tx ++ */ ++ dprintk("poll result = POLLERR\n"); ++ return POLLERR; ++ } + +- dprintk("poll result = %s\n", +- lirc_buffer_empty(&rx->buf) ? "0" : "POLLIN|POLLRDNORM"); ++ /* ++ * Add our lirc_buffer's wait_queue to the poll_table. A wake up on ++ * that buffer's wait queue indicates we may have a new poll status. ++ */ ++ poll_wait(filep, &rbuf->wait_poll, wait); + +- ret = lirc_buffer_empty(&rx->buf) ? 0 : (POLLIN|POLLRDNORM); ++ /* Indicate what ops could happen immediately without blocking */ ++ ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM); + +- mutex_unlock(&rx->buf_lock); ++ dprintk("poll result = %s\n", ret ? "POLLIN|POLLRDNORM" : "none"); + return ret; + } + +@@ -1030,11 +1231,9 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) + { + struct IR *ir = filep->private_data; + int result; +- unsigned long mode, features = 0; ++ unsigned long mode, features; + +- features |= LIRC_CAN_SEND_PULSE; +- if (ir->rx != NULL) +- features |= LIRC_CAN_REC_LIRCCODE; ++ features = ir->l.features; + + switch (cmd) { + case LIRC_GET_LENGTH: +@@ -1061,9 +1260,15 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) + result = -EINVAL; + break; + case LIRC_GET_SEND_MODE: ++ if (!(features&LIRC_CAN_SEND_MASK)) ++ return -ENOSYS; ++ + result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); + break; + case LIRC_SET_SEND_MODE: ++ if (!(features&LIRC_CAN_SEND_MASK)) ++ return -ENOSYS; ++ + result = get_user(mode, (unsigned long *) arg); + if (!result && mode != LIRC_MODE_PULSE) + return -EINVAL; +@@ -1074,13 +1279,24 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) + return result; + } + +-/* ir_devices_lock must be held */ +-static struct IR *find_ir_device_by_minor(unsigned int minor) ++static struct IR *get_ir_device_by_minor(unsigned int minor) + { +- if (minor >= MAX_IRCTL_DEVICES) +- return NULL; ++ struct IR *ir; ++ struct IR *ret = NULL; ++ ++ mutex_lock(&ir_devices_lock); ++ ++ if (!list_empty(&ir_devices_list)) { ++ list_for_each_entry(ir, &ir_devices_list, list) { ++ if (ir->l.minor == minor) { ++ ret = get_ir_device(ir, true); ++ break; ++ } ++ } ++ } + +- return ir_devices[minor]; ++ mutex_unlock(&ir_devices_lock); ++ return ret; + } + + /* +@@ -1090,31 +1306,20 @@ static struct IR *find_ir_device_by_minor(unsigned int minor) + static int open(struct inode *node, struct file *filep) + { + struct IR *ir; +- int ret; + unsigned int minor = MINOR(node->i_rdev); + + /* find our IR struct */ +- mutex_lock(&ir_devices_lock); +- ir = find_ir_device_by_minor(minor); +- mutex_unlock(&ir_devices_lock); ++ ir = get_ir_device_by_minor(minor); + + if (ir == NULL) + return -ENODEV; + +- /* increment in use count */ +- mutex_lock(&ir->ir_lock); +- ++ir->open; +- ret = set_use_inc(ir); +- if (ret != 0) { +- --ir->open; +- mutex_unlock(&ir->ir_lock); +- return ret; +- } +- mutex_unlock(&ir->ir_lock); ++ atomic_inc(&ir->open_count); + + /* stash our IR struct */ + filep->private_data = ir; + ++ nonseekable_open(node, filep); + return 0; + } + +@@ -1128,22 +1333,12 @@ static int close(struct inode *node, struct file *filep) + return -ENODEV; + } + +- /* decrement in use count */ +- mutex_lock(&ir->ir_lock); +- --ir->open; +- set_use_dec(ir); +- mutex_unlock(&ir->ir_lock); ++ atomic_dec(&ir->open_count); + ++ put_ir_device(ir, false); + return 0; + } + +-static struct lirc_driver lirc_template = { +- .name = "lirc_zilog", +- .set_use_inc = set_use_inc, +- .set_use_dec = set_use_dec, +- .owner = THIS_MODULE +-}; +- + static int ir_remove(struct i2c_client *client); + static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); + +@@ -1170,7 +1365,7 @@ static struct i2c_driver driver = { + + static const struct file_operations lirc_fops = { + .owner = THIS_MODULE, +- .llseek = lseek, ++ .llseek = no_llseek, + .read = read, + .write = write, + .poll = poll, +@@ -1182,97 +1377,64 @@ static const struct file_operations lirc_fops = { + .release = close + }; + +-static void destroy_rx_kthread(struct IR_rx *rx) +-{ +- /* end up polling thread */ +- if (rx != NULL && !IS_ERR_OR_NULL(rx->task)) { +- kthread_stop(rx->task); +- rx->task = NULL; +- } +-} ++static struct lirc_driver lirc_template = { ++ .name = "lirc_zilog", ++ .minor = -1, ++ .code_length = 13, ++ .buffer_size = BUFLEN / 2, ++ .sample_rate = 0, /* tell lirc_dev to not start its own kthread */ ++ .chunk_size = 2, ++ .set_use_inc = set_use_inc, ++ .set_use_dec = set_use_dec, ++ .fops = &lirc_fops, ++ .owner = THIS_MODULE, ++}; + +-/* ir_devices_lock must be held */ +-static int add_ir_device(struct IR *ir) ++static int ir_remove(struct i2c_client *client) + { +- int i; +- +- for (i = 0; i < MAX_IRCTL_DEVICES; i++) +- if (ir_devices[i] == NULL) { +- ir_devices[i] = ir; +- break; ++ if (strncmp("ir_tx_z8", client->name, 8) == 0) { ++ struct IR_tx *tx = i2c_get_clientdata(client); ++ if (tx != NULL) { ++ mutex_lock(&tx->client_lock); ++ tx->c = NULL; ++ mutex_unlock(&tx->client_lock); ++ put_ir_tx(tx, false); + } +- +- return i == MAX_IRCTL_DEVICES ? -ENOMEM : i; +-} +- +-/* ir_devices_lock must be held */ +-static void del_ir_device(struct IR *ir) +-{ +- int i; +- +- for (i = 0; i < MAX_IRCTL_DEVICES; i++) +- if (ir_devices[i] == ir) { +- ir_devices[i] = NULL; +- break; ++ } else if (strncmp("ir_rx_z8", client->name, 8) == 0) { ++ struct IR_rx *rx = i2c_get_clientdata(client); ++ if (rx != NULL) { ++ mutex_lock(&rx->client_lock); ++ rx->c = NULL; ++ mutex_unlock(&rx->client_lock); ++ put_ir_rx(rx, false); + } +-} +- +-static int ir_remove(struct i2c_client *client) +-{ +- struct IR *ir = i2c_get_clientdata(client); +- +- mutex_lock(&ir_devices_lock); +- +- if (ir == NULL) { +- /* We destroyed everything when the first client came through */ +- mutex_unlock(&ir_devices_lock); +- return 0; + } +- +- /* Good-bye LIRC */ +- lirc_unregister_driver(ir->l.minor); +- +- /* Good-bye Rx */ +- destroy_rx_kthread(ir->rx); +- if (ir->rx != NULL) { +- if (ir->rx->buf.fifo_initialized) +- lirc_buffer_free(&ir->rx->buf); +- i2c_set_clientdata(ir->rx->c, NULL); +- kfree(ir->rx); +- } +- +- /* Good-bye Tx */ +- i2c_set_clientdata(ir->tx->c, NULL); +- kfree(ir->tx); +- +- /* Good-bye IR */ +- del_ir_device(ir); +- kfree(ir); +- +- mutex_unlock(&ir_devices_lock); + return 0; + } + + + /* ir_devices_lock must be held */ +-static struct IR *find_ir_device_by_adapter(struct i2c_adapter *adapter) ++static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter) + { +- int i; +- struct IR *ir = NULL; ++ struct IR *ir; + +- for (i = 0; i < MAX_IRCTL_DEVICES; i++) +- if (ir_devices[i] != NULL && +- ir_devices[i]->adapter == adapter) { +- ir = ir_devices[i]; +- break; ++ if (list_empty(&ir_devices_list)) ++ return NULL; ++ ++ list_for_each_entry(ir, &ir_devices_list, list) ++ if (ir->adapter == adapter) { ++ get_ir_device(ir, true); ++ return ir; + } + +- return ir; ++ return NULL; + } + + static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) + { + struct IR *ir; ++ struct IR_tx *tx; ++ struct IR_rx *rx; + struct i2c_adapter *adap = client->adapter; + int ret; + bool tx_probe = false; +@@ -1296,133 +1458,170 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) + mutex_lock(&ir_devices_lock); + + /* Use a single struct IR instance for both the Rx and Tx functions */ +- ir = find_ir_device_by_adapter(adap); ++ ir = get_ir_device_by_adapter(adap); + if (ir == NULL) { + ir = kzalloc(sizeof(struct IR), GFP_KERNEL); + if (ir == NULL) { + ret = -ENOMEM; + goto out_no_ir; + } ++ kref_init(&ir->ref); ++ + /* store for use in ir_probe() again, and open() later on */ +- ret = add_ir_device(ir); +- if (ret) +- goto out_free_ir; ++ INIT_LIST_HEAD(&ir->list); ++ list_add_tail(&ir->list, &ir_devices_list); + + ir->adapter = adap; + mutex_init(&ir->ir_lock); ++ atomic_set(&ir->open_count, 0); ++ spin_lock_init(&ir->tx_ref_lock); ++ spin_lock_init(&ir->rx_ref_lock); + + /* set lirc_dev stuff */ + memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); +- ir->l.minor = minor; /* module option */ +- ir->l.code_length = 13; +- ir->l.rbuf = NULL; +- ir->l.fops = &lirc_fops; +- ir->l.data = ir; +- ir->l.dev = &adap->dev; +- ir->l.sample_rate = 0; ++ /* ++ * FIXME this is a pointer reference to us, but no refcount. ++ * ++ * This OK for now, since lirc_dev currently won't touch this ++ * buffer as we provide our own lirc_fops. ++ * ++ * Currently our own lirc_fops rely on this ir->l.rbuf pointer ++ */ ++ ir->l.rbuf = &ir->rbuf; ++ ir->l.dev = &adap->dev; ++ ret = lirc_buffer_init(ir->l.rbuf, ++ ir->l.chunk_size, ir->l.buffer_size); ++ if (ret) ++ goto out_put_ir; + } + + if (tx_probe) { ++ /* Get the IR_rx instance for later, if already allocated */ ++ rx = get_ir_rx(ir); ++ + /* Set up a struct IR_tx instance */ +- ir->tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); +- if (ir->tx == NULL) { ++ tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); ++ if (tx == NULL) { + ret = -ENOMEM; +- goto out_free_xx; ++ goto out_put_xx; + } +- +- ir->tx->c = client; +- ir->tx->need_boot = 1; +- ir->tx->post_tx_ready_poll = ++ kref_init(&tx->ref); ++ ir->tx = tx; ++ ++ ir->l.features |= LIRC_CAN_SEND_PULSE; ++ mutex_init(&tx->client_lock); ++ tx->c = client; ++ tx->need_boot = 1; ++ tx->post_tx_ready_poll = + (id->driver_data & ID_FLAG_HDPVR) ? false : true; ++ ++ /* An ir ref goes to the struct IR_tx instance */ ++ tx->ir = get_ir_device(ir, true); ++ ++ /* A tx ref goes to the i2c_client */ ++ i2c_set_clientdata(client, get_ir_tx(ir)); ++ ++ /* ++ * Load the 'firmware'. We do this before registering with ++ * lirc_dev, so the first firmware load attempt does not happen ++ * after a open() or write() call on the device. ++ * ++ * Failure here is not deemed catastrophic, so the receiver will ++ * still be usable. Firmware load will be retried in write(), ++ * if it is needed. ++ */ ++ fw_load(tx); ++ ++ /* Proceed only if the Rx client is also ready or not needed */ ++ if (rx == NULL && !tx_only) { ++ zilog_info("probe of IR Tx on %s (i2c-%d) done. Waiting" ++ " on IR Rx.\n", adap->name, adap->nr); ++ goto out_ok; ++ } + } else { ++ /* Get the IR_tx instance for later, if already allocated */ ++ tx = get_ir_tx(ir); ++ + /* Set up a struct IR_rx instance */ +- ir->rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); +- if (ir->rx == NULL) { ++ rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); ++ if (rx == NULL) { + ret = -ENOMEM; +- goto out_free_xx; ++ goto out_put_xx; + } ++ kref_init(&rx->ref); ++ ir->rx = rx; + +- ret = lirc_buffer_init(&ir->rx->buf, 2, BUFLEN / 2); +- if (ret) +- goto out_free_xx; +- +- mutex_init(&ir->rx->buf_lock); +- ir->rx->c = client; +- ir->rx->hdpvr_data_fmt = ++ ir->l.features |= LIRC_CAN_REC_LIRCCODE; ++ mutex_init(&rx->client_lock); ++ rx->c = client; ++ rx->hdpvr_data_fmt = + (id->driver_data & ID_FLAG_HDPVR) ? true : false; + +- /* set lirc_dev stuff */ +- ir->l.rbuf = &ir->rx->buf; +- } +- +- i2c_set_clientdata(client, ir); ++ /* An ir ref goes to the struct IR_rx instance */ ++ rx->ir = get_ir_device(ir, true); + +- /* Proceed only if we have the required Tx and Rx clients ready to go */ +- if (ir->tx == NULL || +- (ir->rx == NULL && !tx_only)) { +- zilog_info("probe of IR %s on %s (i2c-%d) done. Waiting on " +- "IR %s.\n", tx_probe ? "Tx" : "Rx", adap->name, +- adap->nr, tx_probe ? "Rx" : "Tx"); +- goto out_ok; +- } ++ /* An rx ref goes to the i2c_client */ ++ i2c_set_clientdata(client, get_ir_rx(ir)); + +- /* initialise RX device */ +- if (ir->rx != NULL) { +- /* try to fire up polling thread */ +- ir->rx->task = kthread_run(lirc_thread, ir, +- "zilog-rx-i2c-%d", adap->nr); +- if (IS_ERR(ir->rx->task)) { +- ret = PTR_ERR(ir->rx->task); ++ /* ++ * Start the polling thread. ++ * It will only perform an empty loop around schedule_timeout() ++ * until we register with lirc_dev and the first user open() ++ */ ++ /* An ir ref goes to the new rx polling kthread */ ++ rx->task = kthread_run(lirc_thread, get_ir_device(ir, true), ++ "zilog-rx-i2c-%d", adap->nr); ++ if (IS_ERR(rx->task)) { ++ ret = PTR_ERR(rx->task); + zilog_error("%s: could not start IR Rx polling thread" + "\n", __func__); +- goto out_free_xx; ++ /* Failed kthread, so put back the ir ref */ ++ put_ir_device(ir, true); ++ /* Failure exit, so put back rx ref from i2c_client */ ++ i2c_set_clientdata(client, NULL); ++ put_ir_rx(rx, true); ++ ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; ++ goto out_put_xx; ++ } ++ ++ /* Proceed only if the Tx client is also ready */ ++ if (tx == NULL) { ++ zilog_info("probe of IR Rx on %s (i2c-%d) done. Waiting" ++ " on IR Tx.\n", adap->name, adap->nr); ++ goto out_ok; + } + } + + /* register with lirc */ ++ ir->l.minor = minor; /* module option: user requested minor number */ + ir->l.minor = lirc_register_driver(&ir->l); + if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { + zilog_error("%s: \"minor\" must be between 0 and %d (%d)!\n", + __func__, MAX_IRCTL_DEVICES-1, ir->l.minor); + ret = -EBADRQC; +- goto out_free_thread; ++ goto out_put_xx; + } ++ zilog_info("IR unit on %s (i2c-%d) registered as lirc%d and ready\n", ++ adap->name, adap->nr, ir->l.minor); + +- /* +- * if we have the tx device, load the 'firmware'. We do this +- * after registering with lirc as otherwise hotplug seems to take +- * 10s to create the lirc device. +- */ +- ret = tx_init(ir->tx); +- if (ret != 0) +- goto out_unregister; +- +- zilog_info("probe of IR %s on %s (i2c-%d) done. IR unit ready.\n", +- tx_probe ? "Tx" : "Rx", adap->name, adap->nr); + out_ok: ++ if (rx != NULL) ++ put_ir_rx(rx, true); ++ if (tx != NULL) ++ put_ir_tx(tx, true); ++ put_ir_device(ir, true); ++ zilog_info("probe of IR %s on %s (i2c-%d) done\n", ++ tx_probe ? "Tx" : "Rx", adap->name, adap->nr); + mutex_unlock(&ir_devices_lock); + return 0; + +-out_unregister: +- lirc_unregister_driver(ir->l.minor); +-out_free_thread: +- destroy_rx_kthread(ir->rx); +-out_free_xx: +- if (ir->rx != NULL) { +- if (ir->rx->buf.fifo_initialized) +- lirc_buffer_free(&ir->rx->buf); +- if (ir->rx->c != NULL) +- i2c_set_clientdata(ir->rx->c, NULL); +- kfree(ir->rx); +- } +- if (ir->tx != NULL) { +- if (ir->tx->c != NULL) +- i2c_set_clientdata(ir->tx->c, NULL); +- kfree(ir->tx); +- } +-out_free_ir: +- del_ir_device(ir); +- kfree(ir); ++out_put_xx: ++ if (rx != NULL) ++ put_ir_rx(rx, true); ++ if (tx != NULL) ++ put_ir_tx(tx, true); ++out_put_ir: ++ put_ir_device(ir, true); + out_no_ir: + zilog_error("%s: probing IR %s on %s (i2c-%d) failed with %d\n", + __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, +@@ -1438,7 +1637,6 @@ static int __init zilog_init(void) + zilog_notify("Zilog/Hauppauge IR driver initializing\n"); + + mutex_init(&tx_data_lock); +- mutex_init(&ir_devices_lock); + + request_module("firmware_class"); + +diff --git a/include/media/rc-map.h b/include/media/rc-map.h +index d843afc..9184751 100644 +--- a/include/media/rc-map.h ++++ b/include/media/rc-map.h +@@ -94,7 +94,7 @@ void rc_map_init(void); + #define RC_MAP_GADMEI_RM008Z "rc-gadmei-rm008z" + #define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" + #define RC_MAP_GOTVIEW7135 "rc-gotview7135" +-#define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge-new" ++#define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge" + #define RC_MAP_IMON_MCE "rc-imon-mce" + #define RC_MAP_IMON_PAD "rc-imon-pad" + #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" +@@ -125,7 +125,7 @@ void rc_map_init(void); + #define RC_MAP_PROTEUS_2309 "rc-proteus-2309" + #define RC_MAP_PURPLETV "rc-purpletv" + #define RC_MAP_PV951 "rc-pv951" +-#define RC_MAP_RC5_HAUPPAUGE_NEW "rc-rc5-hauppauge-new" ++#define RC_MAP_HAUPPAUGE "rc-hauppauge" + #define RC_MAP_RC5_TV "rc-rc5-tv" + #define RC_MAP_RC6_MCE "rc-rc6-mce" + #define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys" +diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h +index 6e96b26..f80b537 100644 +--- a/include/media/soc_camera.h ++++ b/include/media/soc_camera.h +@@ -30,6 +30,8 @@ struct soc_camera_device { + struct device *pdev; /* Platform device */ + s32 user_width; + s32 user_height; ++ u32 bytesperline; /* for padding, zero if unused */ ++ u32 sizeimage; + enum v4l2_colorspace colorspace; + unsigned char iface; /* Host number */ + unsigned char devnum; /* Device number per host */ diff --git a/linux-2.6-v4l-dvb-uvcvideo-update.patch b/linux-2.6-v4l-dvb-uvcvideo-update.patch deleted file mode 100644 index 3251c7fa3..000000000 --- a/linux-2.6-v4l-dvb-uvcvideo-update.patch +++ /dev/null @@ -1,362 +0,0 @@ -From: Martin Rubli -Date: Wed, 19 May 2010 22:51:56 +0000 (+0200) -Subject: uvcvideo: Add support for absolute pan/tilt controls -X-Git-Url: http://git.linuxtv.org/pinchartl/uvcvideo.git?a=commitdiff_plain;h=d3c2f664ec76aff14c3841c99e84cd78d7227f79 - -uvcvideo: Add support for absolute pan/tilt controls - -Signed-off-by: Martin Rubli ---- - -diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c -index aa0720a..5ec2f4a 100644 ---- a/drivers/media/video/uvc/uvc_ctrl.c -+++ b/drivers/media/video/uvc/uvc_ctrl.c -@@ -606,6 +606,26 @@ static struct uvc_control_mapping uvc_ctrl_mappings[] = { - .set = uvc_ctrl_set_zoom, - }, - { -+ .id = V4L2_CID_PAN_ABSOLUTE, -+ .name = "Pan (Absolute)", -+ .entity = UVC_GUID_UVC_CAMERA, -+ .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, -+ .size = 32, -+ .offset = 0, -+ .v4l2_type = V4L2_CTRL_TYPE_INTEGER, -+ .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, -+ }, -+ { -+ .id = V4L2_CID_TILT_ABSOLUTE, -+ .name = "Tilt (Absolute)", -+ .entity = UVC_GUID_UVC_CAMERA, -+ .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, -+ .size = 32, -+ .offset = 32, -+ .v4l2_type = V4L2_CTRL_TYPE_INTEGER, -+ .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, -+ }, -+ { - .id = V4L2_CID_PRIVACY, - .name = "Privacy", - .entity = UVC_GUID_UVC_CAMERA, -From: Hans de Goede -Date: Wed, 19 May 2010 23:15:00 +0000 (+0200) -Subject: uvcvideo: Make button controls work properly -X-Git-Url: http://git.linuxtv.org/pinchartl/uvcvideo.git?a=commitdiff_plain;h=2bd47ad4894bfaf1a97660b821cbc46439a614d6 - -uvcvideo: Make button controls work properly - -According to the v4l2 spec, writing any value to a button control should -result in the action belonging to the button control being triggered. -UVC cams however want to see a 1 written, this patch fixes this by -overriding whatever value user space passed in with -1 (0xffffffff) when -the control is a button control. - -Signed-off-by: Hans de Goede ---- - -diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c -index 5ec2f4a..8bb825d 100644 ---- a/drivers/media/video/uvc/uvc_ctrl.c -+++ b/drivers/media/video/uvc/uvc_ctrl.c -@@ -698,6 +698,14 @@ static void uvc_set_le_value(struct uvc_control_mapping *mapping, - int offset = mapping->offset; - __u8 mask; - -+ /* According to the v4l2 spec, writing any value to a button control -+ * should result in the action belonging to the button control being -+ * triggered. UVC devices however want to see a 1 written -> override -+ * value. -+ */ -+ if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON) -+ value = -1; -+ - data += offset / 8; - offset &= 7; - -From: Laurent Pinchart -Date: Thu, 18 Feb 2010 19:38:52 +0000 (+0100) -Subject: uvcvideo: Support menu controls in the control mapping API -X-Git-Url: http://git.linuxtv.org/pinchartl/uvcvideo.git?a=commitdiff_plain;h=4930f2662e47d33e5baedac620da401a225bc3a8 - -uvcvideo: Support menu controls in the control mapping API - -The UVCIOC_CTRL_MAP ioctl doesn't support menu entries for menu -controls. As the uvc_xu_control_mapping structure has no reserved -fields, this can't be fixed while keeping ABI compatibility. - -Modify the UVCIOC_CTRL_MAP ioctl to add menu entries support, and define -UVCIOC_CTRL_MAP_OLD that supports the old ABI without any ability to add -menu controls. - -Signed-off-by: Laurent Pinchart ---- - -diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c -index 8bb825d..c88d72e 100644 ---- a/drivers/media/video/uvc/uvc_ctrl.c -+++ b/drivers/media/video/uvc/uvc_ctrl.c -@@ -1606,6 +1606,28 @@ void uvc_ctrl_cleanup_device(struct uvc_device *dev) - } - } - -+void uvc_ctrl_cleanup(void) -+{ -+ struct uvc_control_info *info; -+ struct uvc_control_info *ni; -+ struct uvc_control_mapping *mapping; -+ struct uvc_control_mapping *nm; -+ -+ list_for_each_entry_safe(info, ni, &uvc_driver.controls, list) { -+ if (!(info->flags & UVC_CONTROL_EXTENSION)) -+ continue; -+ -+ list_for_each_entry_safe(mapping, nm, &info->mappings, list) { -+ list_del(&mapping->list); -+ kfree(mapping->menu_info); -+ kfree(mapping); -+ } -+ -+ list_del(&info->list); -+ kfree(info); -+ } -+} -+ - void uvc_ctrl_init(void) - { - struct uvc_control_info *ctrl = uvc_ctrls; -diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c -index 838b56f..34818c1 100644 ---- a/drivers/media/video/uvc/uvc_driver.c -+++ b/drivers/media/video/uvc/uvc_driver.c -@@ -2261,6 +2261,7 @@ static int __init uvc_init(void) - static void __exit uvc_cleanup(void) - { - usb_deregister(&uvc_driver.driver); -+ uvc_ctrl_cleanup(); - } - - module_init(uvc_init); -diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c -index 7c9ab29..485a899 100644 ---- a/drivers/media/video/uvc/uvc_v4l2.c -+++ b/drivers/media/video/uvc/uvc_v4l2.c -@@ -29,6 +29,71 @@ - #include "uvcvideo.h" - - /* ------------------------------------------------------------------------ -+ * UVC ioctls -+ */ -+static int uvc_ioctl_ctrl_map(struct uvc_xu_control_mapping *xmap, int old) -+{ -+ struct uvc_control_mapping *map; -+ unsigned int size; -+ int ret; -+ -+ map = kzalloc(sizeof *map, GFP_KERNEL); -+ if (map == NULL) -+ return -ENOMEM; -+ -+ map->id = xmap->id; -+ memcpy(map->name, xmap->name, sizeof map->name); -+ memcpy(map->entity, xmap->entity, sizeof map->entity); -+ map->selector = xmap->selector; -+ map->size = xmap->size; -+ map->offset = xmap->offset; -+ map->v4l2_type = xmap->v4l2_type; -+ map->data_type = xmap->data_type; -+ -+ switch (xmap->v4l2_type) { -+ case V4L2_CTRL_TYPE_INTEGER: -+ case V4L2_CTRL_TYPE_BOOLEAN: -+ case V4L2_CTRL_TYPE_BUTTON: -+ break; -+ -+ case V4L2_CTRL_TYPE_MENU: -+ if (old) { -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ size = xmap->menu_count * sizeof(*map->menu_info); -+ map->menu_info = kmalloc(size, GFP_KERNEL); -+ if (map->menu_info == NULL) { -+ ret = -ENOMEM; -+ goto done; -+ } -+ -+ if (copy_from_user(map->menu_info, xmap->menu_info, size)) { -+ ret = -EFAULT; -+ goto done; -+ } -+ -+ map->menu_count = xmap->menu_count; -+ break; -+ -+ default: -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ ret = uvc_ctrl_add_mapping(map); -+ -+done: -+ if (ret < 0) { -+ kfree(map->menu_info); -+ kfree(map); -+ } -+ -+ return ret; -+} -+ -+/* ------------------------------------------------------------------------ - * V4L2 interface - */ - -@@ -974,7 +1039,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) - info->flags = xinfo->flags; - - info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | -- UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF; -+ UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | -+ UVC_CONTROL_EXTENSION; - - ret = uvc_ctrl_add_info(info); - if (ret < 0) -@@ -982,32 +1048,12 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) - break; - } - -+ case UVCIOC_CTRL_MAP_OLD: - case UVCIOC_CTRL_MAP: -- { -- struct uvc_xu_control_mapping *xmap = arg; -- struct uvc_control_mapping *map; -- - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - -- map = kzalloc(sizeof *map, GFP_KERNEL); -- if (map == NULL) -- return -ENOMEM; -- -- map->id = xmap->id; -- memcpy(map->name, xmap->name, sizeof map->name); -- memcpy(map->entity, xmap->entity, sizeof map->entity); -- map->selector = xmap->selector; -- map->size = xmap->size; -- map->offset = xmap->offset; -- map->v4l2_type = xmap->v4l2_type; -- map->data_type = xmap->data_type; -- -- ret = uvc_ctrl_add_mapping(map); -- if (ret < 0) -- kfree(map); -- break; -- } -+ return uvc_ioctl_ctrl_map(arg, cmd == UVCIOC_CTRL_MAP_OLD); - - case UVCIOC_CTRL_GET: - return uvc_xu_ctrl_query(chain, arg, 0); -diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h -index d1f8840..14f77e4 100644 ---- a/drivers/media/video/uvc/uvcvideo.h -+++ b/drivers/media/video/uvc/uvcvideo.h -@@ -27,6 +27,8 @@ - #define UVC_CONTROL_RESTORE (1 << 6) - /* Control can be updated by the camera. */ - #define UVC_CONTROL_AUTO_UPDATE (1 << 7) -+/* Control is an extension unit control. */ -+#define UVC_CONTROL_EXTENSION (1 << 8) - - #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ - UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ -@@ -40,6 +42,15 @@ struct uvc_xu_control_info { - __u32 flags; - }; - -+struct uvc_menu_info { -+ __u32 value; -+ __u8 name[32]; -+}; -+ -+struct uvc_xu_control_mapping_old { -+ __u8 reserved[64]; -+}; -+ - struct uvc_xu_control_mapping { - __u32 id; - __u8 name[32]; -@@ -50,6 +61,11 @@ struct uvc_xu_control_mapping { - __u8 offset; - enum v4l2_ctrl_type v4l2_type; - __u32 data_type; -+ -+ struct uvc_menu_info __user *menu_info; -+ __u32 menu_count; -+ -+ __u32 reserved[4]; - }; - - struct uvc_xu_control { -@@ -60,6 +76,7 @@ struct uvc_xu_control { - }; - - #define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) -+#define UVCIOC_CTRL_MAP_OLD _IOWR('U', 2, struct uvc_xu_control_mapping_old) - #define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) - #define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) - #define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) -@@ -198,11 +215,6 @@ struct uvc_streaming_control { - __u8 bMaxVersion; - }; - --struct uvc_menu_info { -- __u32 value; -- __u8 name[32]; --}; -- - struct uvc_control_info { - struct list_head list; - struct list_head mappings; -@@ -625,6 +637,7 @@ extern int uvc_ctrl_init_device(struct uvc_device *dev); - extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); - extern int uvc_ctrl_resume_device(struct uvc_device *dev); - extern void uvc_ctrl_init(void); -+extern void uvc_ctrl_cleanup(void); - - extern int uvc_ctrl_begin(struct uvc_video_chain *chain); - extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback); -From: Laurent Pinchart -Date: Fri, 25 Jun 2010 07:58:43 +0000 (+0200) -Subject: uvcvideo: Add support for Manta MM-353 Plako -X-Git-Url: http://git.linuxtv.org/pinchartl/uvcvideo.git?a=commitdiff_plain;h=352e661e1f347390a86cf34bc5e41adbdd1caa41 - -uvcvideo: Add support for Manta MM-353 Plako - -The camera requires the PROBE_MINMAX quirk. Add a corresponding entry -in the device IDs list - -Signed-off-by: Laurent Pinchart ---- - -diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c -index 34818c1..1a89384 100644 ---- a/drivers/media/video/uvc/uvc_driver.c -+++ b/drivers/media/video/uvc/uvc_driver.c -@@ -2174,6 +2174,15 @@ static struct usb_device_id uvc_ids[] = { - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, -+ /* Manta MM-353 Plako */ -+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE -+ | USB_DEVICE_ID_MATCH_INT_INFO, -+ .idVendor = 0x18ec, -+ .idProduct = 0x3188, -+ .bInterfaceClass = USB_CLASS_VIDEO, -+ .bInterfaceSubClass = 1, -+ .bInterfaceProtocol = 0, -+ .driver_info = UVC_QUIRK_PROBE_MINMAX }, - /* FSC WebCam V30S */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, From 05118fa9b47396dbb27151d95e2dff2c1c8e8859 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Fri, 22 Apr 2011 09:05:22 -0400 Subject: [PATCH 33/99] iwlwifi: fix scanning while channel changing --- ...et-tx-power-when-channel-is-changing.patch | 99 +++++++++++++++++++ kernel.spec | 10 +- 2 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch diff --git a/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch b/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch new file mode 100644 index 000000000..3583c6631 --- /dev/null +++ b/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch @@ -0,0 +1,99 @@ +From dda82c37c366672fa74499f4b639d059a802d16e Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Fri, 28 Jan 2011 16:47:44 +0100 +Subject: [PATCH] iwlwifi: do not set tx power when channel is changing + +Mac80211 can request for tx power and channel change in one ->config +call. If that happens, *_send_tx_power functions will try to setup tx +power for old channel, what can be not correct because we already change +the band. I.e error "Failed to get channel info for channel 140 [0]", +can be printed frequently when operating in software scanning mode. + +Signed-off-by: Stanislaw Gruszka +Acked-by: Wey-Yi Guy +Signed-off-by: John W. Linville +--- + drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- + drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 5 ++--- + drivers/net/wireless/iwlwifi/iwl-core.c | 13 ++++++++++--- + 4 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c +index 39b6f16..4e7b58b 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-3945.c ++++ b/drivers/net/wireless/iwlwifi/iwl-3945.c +@@ -1823,7 +1823,7 @@ int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ +- rc = priv->cfg->ops->lib->send_tx_power(priv); ++ rc = iwl_set_tx_power(priv, priv->tx_power_next, true); + if (rc) { + IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); + return rc; +diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c +index 91a9f52..992caa0 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-4965.c ++++ b/drivers/net/wireless/iwlwifi/iwl-4965.c +@@ -1571,7 +1571,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c + + /* If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames */ +- ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); ++ ret = iwl_set_tx_power(priv, priv->tx_power_next, true); + if (ret) { + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); + return ret; +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index 6d140bd..ee802fe 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -288,10 +288,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) + * If we issue a new RXON command which required a tune then we must + * send a new TXPOWER command or we won't be able to Tx any frames. + * +- * FIXME: which RXON requires a tune? Can we optimise this out in +- * some cases? ++ * It's expected we set power here if channel is changing. + */ +- ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); ++ ret = iwl_set_tx_power(priv, priv->tx_power_next, true); + if (ret) { + IWL_ERR(priv, "Error sending TX power (%d)\n", ret); + return ret; +diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c +index efbde1f..91cac6f 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-core.c ++++ b/drivers/net/wireless/iwlwifi/iwl-core.c +@@ -1161,6 +1161,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) + { + int ret; + s8 prev_tx_power; ++ bool defer; ++ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + + lockdep_assert_held(&priv->mutex); + +@@ -1188,10 +1190,15 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) + if (!iwl_is_ready_rf(priv)) + return -EIO; + +- /* scan complete use tx_power_next, need to be updated */ ++ /* scan complete and commit_rxon use tx_power_next value, ++ * it always need to be updated for newest request */ + priv->tx_power_next = tx_power; +- if (test_bit(STATUS_SCANNING, &priv->status) && !force) { +- IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n"); ++ ++ /* do not set tx power when scanning or channel changing */ ++ defer = test_bit(STATUS_SCANNING, &priv->status) || ++ memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); ++ if (defer && !force) { ++ IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); + return 0; + } + +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index e60fab806..7c1c3caab 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 17 +%global baserelease 18 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -727,6 +727,8 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch +Patch12307: iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1251,6 +1253,9 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Networking +# rhbz#688252 +ApplyPatch iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch + # Misc fixes # The input layer spews crap no-one cares about. ApplyPatch linux-2.6-input-kill-stupid-messages.patch @@ -1956,6 +1961,9 @@ fi # and build. %changelog +* Fri Apr 22 2011 Kyle McMartin 2.6.38.3-18 +- iwlwifi: fix scanning when channel changing (#688252) + * Tue Apr 19 2011 Jarod Wilson - Add basic support for full 32-bit NEC IR scancodes - Add latest patches sent upstream for hid layer expansion and full From 36dff6f30fab0c18b4ec3da4b1d348b65882cfcf Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Fri, 22 Apr 2011 11:07:45 -0400 Subject: [PATCH 34/99] update to 2.6.38.4 --- config-arm | 2 +- config-generic | 2 + kernel.spec | 12 +- perf-gcc460-build-fixes.patch | 227 --------------- sources | 2 +- sparc64_fix_build_errors_with_gcc460.patch | 305 --------------------- 6 files changed, 9 insertions(+), 541 deletions(-) delete mode 100644 perf-gcc460-build-fixes.patch delete mode 100644 sparc64_fix_build_errors_with_gcc460.patch diff --git a/config-arm b/config-arm index e2d8af390..47a024d9f 100644 --- a/config-arm +++ b/config-arm @@ -83,7 +83,7 @@ CONFIG_FB_ARMCLCD=m CONFIG_SND_ARM=y CONFIG_SND_ARMAACI=m -CONFIG_USB_MUSB_HDRC=m +CONFIG_USB_MUSB_HDRC=y # CONFIG_MUSB_PIO_ONLY is not set CONFIG_USB_TUSB6010=y # CONFIG_USB_MUSB_DEBUG is not set diff --git a/config-generic b/config-generic index 61bee74ac..de1ee3763 100644 --- a/config-generic +++ b/config-generic @@ -4495,3 +4495,5 @@ CONFIG_TARGET_CORE=m CONFIG_TCM_IBLOCK=m CONFIG_TCM_FILEIO=m CONFIG_TCM_PSCSI=m + +CONFIG_TEST_KSTRTOX=m diff --git a/kernel.spec b/kernel.spec index 7c1c3caab..716265148 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 18 +%global baserelease 19 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,7 +63,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 3 +%define stable_update 4 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -620,7 +620,6 @@ Patch31: linux-2.6-utrace.patch Patch32: linux-2.6-utrace-ptrace.patch Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch -Patch151: sparc64_fix_build_errors_with_gcc460.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch @@ -705,8 +704,6 @@ Patch2918: flexcop-fix-xlate_proc_name-warning.patch # patches headed upstream -Patch12001: perf-gcc460-build-fixes.patch - Patch12010: add-appleir-usb-driver.patch Patch12016: disable-i8042-check-on-apple-mac.patch @@ -1189,7 +1186,6 @@ ApplyPatch linux-2.6-utrace-ptrace.patch # SPARC64 # ApplyPatch linux-2.6.29-sparc-IOC_TYPECHECK.patch -ApplyPatch sparc64_fix_build_errors_with_gcc460.patch # # Exec shield @@ -1327,7 +1323,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch ApplyPatch flexcop-fix-xlate_proc_name-warning.patch # Patches headed upstream -ApplyPatch perf-gcc460-build-fixes.patch ApplyPatch disable-i8042-check-on-apple-mac.patch @@ -1961,6 +1956,9 @@ fi # and build. %changelog +* Fri Apr 22 2011 Kyle McMartin 2.6.38.4-19 +- Update to 2.6.38.4 + * Fri Apr 22 2011 Kyle McMartin 2.6.38.3-18 - iwlwifi: fix scanning when channel changing (#688252) diff --git a/perf-gcc460-build-fixes.patch b/perf-gcc460-build-fixes.patch deleted file mode 100644 index 074ab6f20..000000000 --- a/perf-gcc460-build-fixes.patch +++ /dev/null @@ -1,227 +0,0 @@ -From linux-kernel-owner@vger.kernel.org Mon Jan 24 11:13:12 2011 -Date: Mon, 24 Jan 2011 11:13:04 -0500 -From: Kyle McMartin -To: mingo@redhat.com -Cc: linux-kernel@vger.kernel.org, acme@redhat.com -Subject: [PATCH] perf: fix gcc 4.6.0 issues with tools/perf -Message-ID: <20110124161304.GK27353@bombadil.infradead.org> - -Hi Ingo, - -GCC 4.6.0 in Fedora rawhide turned up some compile errors in tools/perf -due to the -Werror=unused-but-set-variable flag. - -I've gone through and annotated some of the assignments that had side -effects (ie: return value from a function) with the __used annotation, -and in some cases, just removed unused code. - -In a few cases, we were assigning something useful, but not using it in -later parts of the function. - -regards, Kyle - -kyle@dreadnought:~/src% gcc --version -gcc (GCC) 4.6.0 20110122 (Red Hat 4.6.0-0.3) - ---- - - bench/sched-pipe.c | 2 +- - builtin-sched.c | 12 +++--------- - builtin-top.c | 5 +---- - util/header.c | 2 +- - util/hist.c | 3 --- - util/scripting-engines/trace-event-python.c | 3 +-- - util/symbol.c | 4 ++-- - util/trace-event-parse.c | 2 +- - util/ui/browsers/map.c | 2 +- - 9 files changed, 11 insertions(+), 24 deletions(-) - -diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c -index d9ab3ce..0c7454f 100644 ---- a/tools/perf/bench/sched-pipe.c -+++ b/tools/perf/bench/sched-pipe.c -@@ -55,7 +55,7 @@ int bench_sched_pipe(int argc, const char **argv, - * discarding returned value of read(), write() - * causes error in building environment for perf - */ -- int ret, wait_stat; -+ int __used ret, wait_stat; - pid_t pid, retpid; - - argc = parse_options(argc, argv, options, -diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c -index 29e7ffd..f9e304f 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -369,11 +369,6 @@ static void - process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom) - { - int ret = 0; -- u64 now; -- long long delta; -- -- now = get_nsecs(); -- delta = start_time + atom->timestamp - now; - - switch (atom->type) { - case SCHED_EVENT_RUN: -@@ -562,7 +557,7 @@ static void wait_for_tasks(void) - - static void run_one_test(void) - { -- u64 T0, T1, delta, avg_delta, fluct, std_dev; -+ u64 T0, T1, delta, avg_delta, fluct; - - T0 = get_nsecs(); - wait_for_tasks(); -@@ -578,7 +573,6 @@ static void run_one_test(void) - else - fluct = delta - avg_delta; - sum_fluct += fluct; -- std_dev = sum_fluct / nr_runs / sqrt(nr_runs); - if (!run_avg) - run_avg = delta; - run_avg = (run_avg*9 + delta)/10; -@@ -799,7 +793,7 @@ replay_switch_event(struct trace_switch_event *switch_event, - u64 timestamp, - struct thread *thread __used) - { -- struct task_desc *prev, *next; -+ struct task_desc *prev, __used *next; - u64 timestamp0; - s64 delta; - -@@ -1404,7 +1398,7 @@ map_switch_event(struct trace_switch_event *switch_event, - u64 timestamp, - struct thread *thread __used) - { -- struct thread *sched_out, *sched_in; -+ struct thread *sched_out __used, *sched_in; - int new_shortname; - u64 timestamp0; - s64 delta; -diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c -index 05344c6..373cfc0 100644 ---- a/tools/perf/builtin-top.c -+++ b/tools/perf/builtin-top.c -@@ -182,7 +182,6 @@ static int parse_source(struct sym_entry *syme) - FILE *file; - char command[PATH_MAX*2]; - const char *path; -- u64 len; - - if (!syme) - return -1; -@@ -211,8 +210,6 @@ static int parse_source(struct sym_entry *syme) - } - path = map->dso->long_name; - -- len = sym->end - sym->start; -- - sprintf(command, - "objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s", - BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start), -@@ -1295,7 +1292,7 @@ static int __cmd_top(void) - { - pthread_t thread; - struct perf_evsel *counter; -- int i, ret; -+ int i, ret __used; - /* - * FIXME: perf_session__new should allow passing a O_MMAP, so that all this - * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. -diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c -index 989fa2d..c0e5019 100644 ---- a/tools/perf/util/header.c -+++ b/tools/perf/util/header.c -@@ -1139,7 +1139,7 @@ int event__synthesize_tracing_data(int fd, struct list_head *pattrs, - { - event_t ev; - ssize_t size = 0, aligned_size = 0, padding; -- int err = 0; -+ int err __used = 0; - - memset(&ev, 0, sizeof(ev)); - -diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c -index c749ba6..a01a33d 100644 ---- a/tools/perf/util/hist.c -+++ b/tools/perf/util/hist.c -@@ -1091,7 +1091,6 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head, - char command[PATH_MAX * 2]; - FILE *file; - int err = 0; -- u64 len; - char symfs_filename[PATH_MAX]; - - if (filename) { -@@ -1136,8 +1135,6 @@ fallback: - filename, sym->name, map->unmap_ip(map, sym->start), - map->unmap_ip(map, sym->end)); - -- len = sym->end - sym->start; -- - pr_debug("annotating [%p] %30s : [%p] %30s\n", - dso, dso->long_name, sym, sym->name); - -diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c -index c6d9933..2040b85 100644 ---- a/tools/perf/util/scripting-engines/trace-event-python.c -+++ b/tools/perf/util/scripting-engines/trace-event-python.c -@@ -248,8 +248,7 @@ static void python_process_event(int cpu, void *data, - context = PyCObject_FromVoidPtr(scripting_context, NULL); - - PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); -- PyTuple_SetItem(t, n++, -- PyCObject_FromVoidPtr(scripting_context, NULL)); -+ PyTuple_SetItem(t, n++, context); - - if (handler) { - PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); -diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c -index 15ccfba..52e82cf 100644 ---- a/tools/perf/util/symbol.c -+++ b/tools/perf/util/symbol.c -@@ -1517,8 +1517,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) - symbol_conf.symfs, self->long_name); - break; - case DSO__ORIG_GUEST_KMODULE: -- if (map->groups && map->groups->machine) -- root_dir = map->groups->machine->root_dir; -+ if (map->groups && machine) -+ root_dir = machine->root_dir; - else - root_dir = ""; - snprintf(name, size, "%s%s%s", symbol_conf.symfs, -diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c -index 73a0222..d8e622d 100644 ---- a/tools/perf/util/trace-event-parse.c -+++ b/tools/perf/util/trace-event-parse.c -@@ -153,7 +153,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused) - char *next = NULL; - char *addr_str; - char ch; -- int ret; -+ int ret __used; - int i; - - line = strtok_r(file, "\n", &next); -diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c -index e35437d..3788cad 100644 ---- a/tools/perf/util/ui/browsers/map.c -+++ b/tools/perf/util/ui/browsers/map.c -@@ -40,7 +40,7 @@ static int ui_entry__read(const char *title, char *bf, size_t size, int width) - out_free_form: - newtPopWindow(); - newtFormDestroy(form); -- return 0; -+ return err; - } - - struct map_browser { --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ - diff --git a/sources b/sources index 0e267b8a3..b9a628517 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -b3677121c4b5efcb8128c2000788d0aa patch-2.6.38.3.bz2 +6ef1279c7bd0078fc0fd50aa83e86203 patch-2.6.38.4.bz2 diff --git a/sparc64_fix_build_errors_with_gcc460.patch b/sparc64_fix_build_errors_with_gcc460.patch deleted file mode 100644 index 807032c83..000000000 --- a/sparc64_fix_build_errors_with_gcc460.patch +++ /dev/null @@ -1,305 +0,0 @@ -From dbb988cf34a62e69c8863f212be212c6841004ba Mon Sep 17 00:00:00 2001 -From: David S. Miller -Date: Sat, 26 Feb 2011 23:40:02 -0800 -Subject: [PATCH] sparc64: Fix build errors with gcc-4.6.0 - -Most of the warnings emitted (we fail arch/sparc file -builds with -Werror) were legitimate but harmless, however -one case (n2_pcr_write) was a genuine bug. - -Based almost entirely upon a patch by Sam Ravnborg. - -Reported-by: Dennis Gilmore -Signed-off-by: David S. Miller ---- - arch/sparc/kernel/iommu.c | 3 --- - arch/sparc/kernel/ldc.c | 28 ++++++++++++++++++---------- - arch/sparc/kernel/pci.c | 1 + - arch/sparc/kernel/pci_common.c | 11 +++++++---- - arch/sparc/kernel/pci_fire.c | 2 -- - arch/sparc/kernel/pci_schizo.c | 4 +--- - arch/sparc/kernel/pci_sun4v.c | 3 +-- - arch/sparc/kernel/pcr.c | 2 +- - arch/sparc/kernel/ptrace_64.c | 3 ++- - arch/sparc/kernel/smp_64.c | 11 ++++------- - arch/sparc/kernel/traps_64.c | 3 +-- - 11 files changed, 36 insertions(+), 35 deletions(-) - -diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c -index 72509d0..6f01e8c 100644 ---- a/arch/sparc/kernel/iommu.c -+++ b/arch/sparc/kernel/iommu.c -@@ -333,13 +333,10 @@ static void dma_4u_free_coherent(struct device *dev, size_t size, - void *cpu, dma_addr_t dvma) - { - struct iommu *iommu; -- iopte_t *iopte; - unsigned long flags, order, npages; - - npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT; - iommu = dev->archdata.iommu; -- iopte = iommu->page_table + -- ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT); - - spin_lock_irqsave(&iommu->lock, flags); - -diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c -index df39a0f..732b0bc 100644 ---- a/arch/sparc/kernel/ldc.c -+++ b/arch/sparc/kernel/ldc.c -@@ -790,16 +790,20 @@ static void send_events(struct ldc_channel *lp, unsigned int event_mask) - static irqreturn_t ldc_rx(int irq, void *dev_id) - { - struct ldc_channel *lp = dev_id; -- unsigned long orig_state, hv_err, flags; -+ unsigned long orig_state, flags; - unsigned int event_mask; - - spin_lock_irqsave(&lp->lock, flags); - - orig_state = lp->chan_state; -- hv_err = sun4v_ldc_rx_get_state(lp->id, -- &lp->rx_head, -- &lp->rx_tail, -- &lp->chan_state); -+ -+ /* We should probably check for hypervisor errors here and -+ * reset the LDC channel if we get one. -+ */ -+ sun4v_ldc_rx_get_state(lp->id, -+ &lp->rx_head, -+ &lp->rx_tail, -+ &lp->chan_state); - - ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n", - orig_state, lp->chan_state, lp->rx_head, lp->rx_tail); -@@ -904,16 +908,20 @@ out: - static irqreturn_t ldc_tx(int irq, void *dev_id) - { - struct ldc_channel *lp = dev_id; -- unsigned long flags, hv_err, orig_state; -+ unsigned long flags, orig_state; - unsigned int event_mask = 0; - - spin_lock_irqsave(&lp->lock, flags); - - orig_state = lp->chan_state; -- hv_err = sun4v_ldc_tx_get_state(lp->id, -- &lp->tx_head, -- &lp->tx_tail, -- &lp->chan_state); -+ -+ /* We should probably check for hypervisor errors here and -+ * reset the LDC channel if we get one. -+ */ -+ sun4v_ldc_tx_get_state(lp->id, -+ &lp->tx_head, -+ &lp->tx_tail, -+ &lp->chan_state); - - ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n", - orig_state, lp->chan_state, lp->tx_head, lp->tx_tail); -diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c -index 4137579..f255382 100644 ---- a/arch/sparc/kernel/pci.c -+++ b/arch/sparc/kernel/pci.c -@@ -675,6 +675,7 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) - * humanoid. - */ - err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr); -+ (void) err; - } - list_for_each_entry(child_bus, &bus->children, node) - pci_bus_register_of_sysfs(child_bus); -diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c -index 6c7a33a..6e3874b 100644 ---- a/arch/sparc/kernel/pci_common.c -+++ b/arch/sparc/kernel/pci_common.c -@@ -295,14 +295,17 @@ static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, - unsigned int bus = bus_dev->number; - unsigned int device = PCI_SLOT(devfn); - unsigned int func = PCI_FUNC(devfn); -- unsigned long ret; - - if (config_out_of_range(pbm, bus, devfn, where)) { - /* Do nothing. */ - } else { -- ret = pci_sun4v_config_put(devhandle, -- HV_PCI_DEVICE_BUILD(bus, device, func), -- where, size, value); -+ /* We don't check for hypervisor errors here, but perhaps -+ * we should and influence our return value depending upon -+ * what kind of error is thrown. -+ */ -+ pci_sun4v_config_put(devhandle, -+ HV_PCI_DEVICE_BUILD(bus, device, func), -+ where, size, value); - } - return PCIBIOS_SUCCESSFUL; - } -diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c -index efb896d..75dfeb6 100644 ---- a/arch/sparc/kernel/pci_fire.c -+++ b/arch/sparc/kernel/pci_fire.c -@@ -214,11 +214,9 @@ static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, - - static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) - { -- unsigned long msiqid; - u64 val; - - val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); -- msiqid = (val & MSI_MAP_EQNUM); - - val &= ~MSI_MAP_VALID; - -diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c -index 445a47a..4620eb7 100644 ---- a/arch/sparc/kernel/pci_schizo.c -+++ b/arch/sparc/kernel/pci_schizo.c -@@ -1313,7 +1313,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, - const struct linux_prom64_registers *regs; - struct device_node *dp = op->dev.of_node; - const char *chipset_name; -- int is_pbm_a, err; -+ int err; - - switch (chip_type) { - case PBM_CHIP_TYPE_TOMATILLO: -@@ -1343,8 +1343,6 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, - */ - regs = of_get_property(dp, "reg", NULL); - -- is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); -- - pbm->next = pci_pbm_root; - pci_pbm_root = pbm; - -diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c -index 743344a..859abfd 100644 ---- a/arch/sparc/kernel/pci_sun4v.c -+++ b/arch/sparc/kernel/pci_sun4v.c -@@ -580,7 +580,7 @@ static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm) - { - static const u32 vdma_default[] = { 0x80000000, 0x80000000 }; - struct iommu *iommu = pbm->iommu; -- unsigned long num_tsb_entries, sz, tsbsize; -+ unsigned long num_tsb_entries, sz; - u32 dma_mask, dma_offset; - const u32 *vdma; - -@@ -596,7 +596,6 @@ static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm) - - dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); - num_tsb_entries = vdma[1] / IO_PAGE_SIZE; -- tsbsize = num_tsb_entries * sizeof(iopte_t); - - dma_offset = vdma[0]; - -diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c -index 7c2ced6..8ac23e6 100644 ---- a/arch/sparc/kernel/pcr.c -+++ b/arch/sparc/kernel/pcr.c -@@ -81,7 +81,7 @@ static void n2_pcr_write(u64 val) - unsigned long ret; - - ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); -- if (val != HV_EOK) -+ if (ret != HV_EOK) - write_pcr(val); - } - -diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c -index 9ccc812..96ee50a 100644 ---- a/arch/sparc/kernel/ptrace_64.c -+++ b/arch/sparc/kernel/ptrace_64.c -@@ -1086,6 +1086,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs) - - asmlinkage void syscall_trace_leave(struct pt_regs *regs) - { -+#ifdef CONFIG_AUDITSYSCALL - if (unlikely(current->audit_context)) { - unsigned long tstate = regs->tstate; - int result = AUDITSC_SUCCESS; -@@ -1095,7 +1096,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs) - - audit_syscall_exit(result, regs->u_regs[UREG_I0]); - } -- -+#endif - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_exit(regs, regs->u_regs[UREG_G1]); - -diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c -index 555a76d..3e94a8c 100644 ---- a/arch/sparc/kernel/smp_64.c -+++ b/arch/sparc/kernel/smp_64.c -@@ -189,7 +189,7 @@ static inline long get_delta (long *rt, long *master) - void smp_synchronize_tick_client(void) - { - long i, delta, adj, adjust_latency = 0, done = 0; -- unsigned long flags, rt, master_time_stamp, bound; -+ unsigned long flags, rt, master_time_stamp; - #if DEBUG_TICK_SYNC - struct { - long rt; /* roundtrip time */ -@@ -208,10 +208,8 @@ void smp_synchronize_tick_client(void) - { - for (i = 0; i < NUM_ROUNDS; i++) { - delta = get_delta(&rt, &master_time_stamp); -- if (delta == 0) { -+ if (delta == 0) - done = 1; /* let's lock on to this... */ -- bound = rt; -- } - - if (!done) { - if (i > 0) { -@@ -933,13 +931,12 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu) - void flush_dcache_page_all(struct mm_struct *mm, struct page *page) - { - void *pg_addr; -- int this_cpu; - u64 data0; - - if (tlb_type == hypervisor) - return; - -- this_cpu = get_cpu(); -+ preempt_disable(); - - #ifdef CONFIG_DEBUG_DCFLUSH - atomic_inc(&dcpage_flushes); -@@ -964,7 +961,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page) - } - __local_flush_dcache_page(page); - -- put_cpu(); -+ preempt_enable(); - } - - void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) -diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c -index 42ad2ba..9456472 100644 ---- a/arch/sparc/kernel/traps_64.c -+++ b/arch/sparc/kernel/traps_64.c -@@ -2152,7 +2152,7 @@ static void user_instruction_dump(unsigned int __user *pc) - - void show_stack(struct task_struct *tsk, unsigned long *_ksp) - { -- unsigned long fp, thread_base, ksp; -+ unsigned long fp, ksp; - struct thread_info *tp; - int count = 0; - #ifdef CONFIG_FUNCTION_GRAPH_TRACER -@@ -2173,7 +2173,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) - flushw_all(); - - fp = ksp + STACK_BIAS; -- thread_base = (unsigned long) tp; - - printk("Call Trace:\n"); - do { --- -1.7.4.1 - From 9fd0d88656f799ec5fe6e77356ac5882acebbb0e Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 24 Apr 2011 21:44:39 -0400 Subject: [PATCH 35/99] ppc64: disable CONFIG_TUNE_CELL --- config-powerpc64 | 2 +- kernel.spec | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config-powerpc64 b/config-powerpc64 index 74f33d1aa..2946a0686 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -126,7 +126,7 @@ CONFIG_SCSI_IBMVSCSIS=m CONFIG_SECCOMP=y -CONFIG_TUNE_CELL=y +# CONFIG_TUNE_CELL is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # CONFIG_BLK_DEV_PLATFORM is not set diff --git a/kernel.spec b/kernel.spec index 716265148..bed7d28b1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1956,6 +1956,10 @@ fi # and build. %changelog +* Sun Apr 24 2011 Kyle McMartin +- ppc64: disable TUNE_CELL, which causes problems with illegal instuctions + being generated on non-Cell PPC machines. (#698256) + * Fri Apr 22 2011 Kyle McMartin 2.6.38.4-19 - Update to 2.6.38.4 From cb4a4c8907f97b2a41d24ea81ee12303ee818fa3 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 25 Apr 2011 12:04:09 -0400 Subject: [PATCH 36/99] Fix deadlock in netconsoles netdev notifier handler function Resolves: bz 668231 --- kernel.spec | 9 +++++ linux-2.6-netconsole-deadlock.patch | 56 +++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 linux-2.6-netconsole-deadlock.patch diff --git a/kernel.spec b/kernel.spec index bed7d28b1..d94c7e459 100644 --- a/kernel.spec +++ b/kernel.spec @@ -726,6 +726,9 @@ Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch Patch12307: iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch +#netconsole fixes +Patch12400: linux-2.6-netconsole-deadlock.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1348,6 +1351,9 @@ ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch +#rhbz 668231 +ApplyPatch linux-2.6-netconsole-deadlock.patch + # END OF PATCH APPLICATIONS %endif @@ -1956,6 +1962,9 @@ fi # and build. %changelog +* Mon Apr 25 2011 Neil Horman +- netconsole: fix deadlock in netdev notifier handler + * Sun Apr 24 2011 Kyle McMartin - ppc64: disable TUNE_CELL, which causes problems with illegal instuctions being generated on non-Cell PPC machines. (#698256) diff --git a/linux-2.6-netconsole-deadlock.patch b/linux-2.6-netconsole-deadlock.patch new file mode 100644 index 000000000..677ed760b --- /dev/null +++ b/linux-2.6-netconsole-deadlock.patch @@ -0,0 +1,56 @@ +commit 13f172ff26563995049abe73f6eeba828de3c09d +Author: Neil Horman +Date: Fri Apr 22 08:10:59 2011 +0000 + + netconsole: fix deadlock when removing net driver that netconsole is using (v2) + + A deadlock was reported to me recently that occured when netconsole was being + used in a virtual guest. If the virtio_net driver was removed while netconsole + was setup to use an interface that was driven by that driver, the guest + deadlocked. No backtrace was provided because netconsole was the only console + configured, but it became clear pretty quickly what the problem was. In + netconsole_netdev_event, if we get an unregister event, we call + __netpoll_cleanup with the target_list_lock held and irqs disabled. + __netpoll_cleanup can, if pending netpoll packets are waiting call + cancel_delayed_work_sync, which is a sleeping path. the might_sleep call in + that path gets triggered, causing a console warning to be issued. The + netconsole write handler of course tries to take the target_list_lock again, + which we already hold, causing deadlock. + + The fix is pretty striaghtforward. Simply drop the target_list_lock and + re-enable irqs prior to calling __netpoll_cleanup, the re-acquire the lock, and + restart the loop. Confirmed by myself to fix the problem reported. + + Signed-off-by: Neil Horman + CC: "David S. Miller" + Signed-off-by: David S. Miller + +diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c +index dfb67eb..eb41e44 100644 +--- a/drivers/net/netconsole.c ++++ b/drivers/net/netconsole.c +@@ -671,6 +671,7 @@ static int netconsole_netdev_event(struct notifier_block *this, + goto done; + + spin_lock_irqsave(&target_list_lock, flags); ++restart: + list_for_each_entry(nt, &target_list, list) { + netconsole_target_get(nt); + if (nt->np.dev == dev) { +@@ -683,9 +684,16 @@ static int netconsole_netdev_event(struct notifier_block *this, + * rtnl_lock already held + */ + if (nt->np.dev) { ++ spin_unlock_irqrestore( ++ &target_list_lock, ++ flags); + __netpoll_cleanup(&nt->np); ++ spin_lock_irqsave(&target_list_lock, ++ flags); + dev_put(nt->np.dev); + nt->np.dev = NULL; ++ netconsole_target_put(nt); ++ goto restart; + } + /* Fall through */ + case NETDEV_GOING_DOWN: From caf1c2222ceae7cbfe3fdcc255ef7703afb6590b Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 25 Apr 2011 10:21:49 -0400 Subject: [PATCH 37/99] Trivial IR fixifications Signed-off-by: Jarod Wilson --- kernel.spec | 5 ++ linux-2.6-v4l-dvb-experimental.patch | 85 +++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index d94c7e459..830277888 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1962,6 +1962,11 @@ fi # and build. %changelog +* Mon Apr 25 2011 Jarod Wilson +- ite-cir: fix modular build on powerpc (#698378) +- mceusb: add Dell-branded transceiver device ID +- nuvoton-cir: improve compatibility with lirc raw IR mode + * Mon Apr 25 2011 Neil Horman - netconsole: fix deadlock in netdev notifier handler diff --git a/linux-2.6-v4l-dvb-experimental.patch b/linux-2.6-v4l-dvb-experimental.patch index a5cc5911c..308ca6351 100644 --- a/linux-2.6-v4l-dvb-experimental.patch +++ b/linux-2.6-v4l-dvb-experimental.patch @@ -1,3 +1,37 @@ +commit 9069f7f1ce7309cba021ac9c3527526d8524bd04 +Author: Jarod Wilson +Date: Mon Apr 25 13:50:50 2011 -0400 + + [media] ite-cir: modular build on ppc requires delay.h include + + Signed-off-by: Jarod Wilson + +commit 50f19c24801caaa6d846c62cef93ee54f6e6914f +Author: Jarod Wilson +Date: Mon Apr 25 13:48:18 2011 -0400 + + [media] mceusb: add Dell transceiver ID + + Add device ID for a Dell-branded, Philips device ID transceiver reported + by an OpenELEC user on their forums. + + http://openelec.tv/forum/27-hardware-support/5622-adding-support-for-an-ir-receiver--dell-branded--#5622 + + Signed-off-by: Jarod Wilson + +commit d9193f3784352638b355c9a24c16f1a2e14b0548 +Author: Jarod Wilson +Date: Thu Apr 21 14:21:47 2011 -0400 + + [media] nuvoton-cir: minor tweaks to rc dev init + + - Set a default timeout (matching mceusb.c) and use + ir_raw_event_store_with_filter, which leads to better behavior when + using lirc userspace decoding with this hardware + - Fill in rx_resolution with the value we're using here (50us) + + Signed-off-by: Jarod Wilson + commit 02210203eb4df7fdf1156b24fcf2b7e2a20bf29c Author: Jarod Wilson Date: Tue Apr 19 15:47:34 2011 -0400 @@ -1005,7 +1039,16 @@ index 044fb7a..47a1c5d 100644 }; static struct usb_device_id mceusb_dev_table[] = { -@@ -277,7 +287,8 @@ static struct usb_device_id mceusb_dev_table[] = { +@@ -230,6 +230,8 @@ static struct usb_device_id mceusb_dev_table[] = { + { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, + /* Philips/Spinel plus IR transceiver for ASUS */ + { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, ++ /* Philips IR transceiver (Dell branded) */ ++ { USB_DEVICE(VENDOR_PHILIPS, 0x2093) }, + /* Realtek MCE IR Receiver and card reader */ + { USB_DEVICE(VENDOR_REALTEK, 0x0161), + .driver_info = MULTIFUNCTION }, +@@ -279,7 +289,8 @@ static struct usb_device_id mceusb_dev_table[] = { /* Formosa21 / eHome Infrared Receiver */ { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, /* Formosa aim / Trust MCE Infrared Receiver */ @@ -1015,7 +1058,7 @@ index 044fb7a..47a1c5d 100644 /* Formosa Industrial Computing / Beanbag Emulation Device */ { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, /* Formosa21 / eHome Infrared Receiver */ -@@ -306,7 +317,8 @@ static struct usb_device_id mceusb_dev_table[] = { +@@ -308,7 +319,8 @@ static struct usb_device_id mceusb_dev_table[] = { /* Northstar Systems, Inc. eHome Infrared Transceiver */ { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, /* TiVo PC IR Receiver */ @@ -1123,6 +1166,31 @@ index d4d6449..5d93384 100644 /* Select CIR logical device and enable */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); +@@ -674,7 +674,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) + rawir.pulse ? "pulse" : "space", + rawir.duration); + +- ir_raw_event_store(nvt->rdev, &rawir); ++ ir_raw_event_store_with_filter(nvt->rdev, &rawir); + } + + /* +@@ -1110,12 +1110,12 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) + rdev->input_id.version = nvt->chip_minor; + rdev->driver_name = NVT_DRIVER_NAME; + rdev->map_name = RC_MAP_RC6_MCE; ++ rdev->timeout = US_TO_NS(1000); ++ /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ ++ rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); + #if 0 + rdev->min_timeout = XYZ; + rdev->max_timeout = XYZ; +- rdev->timeout = XYZ; +- /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ +- rdev->rx_resolution = XYZ; + /* tx bits */ + rdev->tx_resolution = XYZ; + #endif diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 048135e..379795d 100644 --- a/drivers/media/rc/nuvoton-cir.h @@ -1243,3 +1311,16 @@ index 9184751..b2bd405 100644 #define RC_MAP_TOTAL_MEDIA_IN_HAND "rc-total-media-in-hand" #define RC_MAP_TREKSTOR "rc-trekstor" #define RC_MAP_TT_1500 "rc-tt-1500" +diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c +index accaf6c..43908a7 100644 +--- a/drivers/media/rc/ite-cir.c ++++ b/drivers/media/rc/ite-cir.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + #include + #include + #include + From 915385f9f0cb1f6cbfa24fe339510318204f78cd Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 26 Apr 2011 23:44:48 -0400 Subject: [PATCH 38/99] Another fix for ASPM powersave mode --- kernel.spec | 15 +++++++--- ...-state-clearing-regardless-of-policy.patch | 29 +++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 pci-enable-aspm-state-clearing-regardless-of-policy.patch diff --git a/kernel.spec b/kernel.spec index 830277888..98df4ba32 100644 --- a/kernel.spec +++ b/kernel.spec @@ -631,9 +631,13 @@ Patch204: linux-2.6-debug-always-inline-kzalloc.patch Patch380: linux-2.6-defaults-pci_no_msi.patch Patch381: linux-2.6-defaults-pci_use_crs.patch -Patch383: linux-2.6-defaults-aspm.patch -Patch385: ima-allow-it-to-be-completely-disabled-and-default-off.patch +# ASPM: enable powersave by default +Patch383: linux-2.6-defaults-aspm.patch +Patch384: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch +Patch385: pci-enable-aspm-state-clearing-regardless-of-policy.patch + +Patch389: ima-allow-it-to-be-completely-disabled-and-default-off.patch Patch390: linux-2.6-defaults-acpi-video.patch Patch391: linux-2.6-acpi-video-dos.patch @@ -717,7 +721,6 @@ Patch12200: acpi_reboot.patch # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch -Patch12207: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch @@ -1236,8 +1239,9 @@ ApplyPatch linux-2.6-defaults-pci_no_msi.patch ApplyPatch linux-2.6-defaults-pci_use_crs.patch # enable ASPM by default on hardware we expect to work ApplyPatch linux-2.6-defaults-aspm.patch -# +# fixes for ASPM powersave mode ApplyPatch pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch +ApplyPatch pci-enable-aspm-state-clearing-regardless-of-policy.patch #ApplyPatch ima-allow-it-to-be-completely-disabled-and-default-off.patch @@ -1962,6 +1966,9 @@ fi # and build. %changelog +* Tue Apr 26 2011 Chuck Ebbert +- Another fix for ASPM powersave mode + * Mon Apr 25 2011 Jarod Wilson - ite-cir: fix modular build on powerpc (#698378) - mceusb: add Dell-branded transceiver device ID diff --git a/pci-enable-aspm-state-clearing-regardless-of-policy.patch b/pci-enable-aspm-state-clearing-regardless-of-policy.patch new file mode 100644 index 000000000..afc977623 --- /dev/null +++ b/pci-enable-aspm-state-clearing-regardless-of-policy.patch @@ -0,0 +1,29 @@ +From: Alex Williamson +Date: Thu, 10 Mar 2011 18:54:16 +0000 (-0700) +Subject: PCI: Enable ASPM state clearing regardless of policy +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjbarnes%2Fpci-2.6.git;a=commitdiff_plain;h=1a4e6a3c049bba1574c2a80af44f0ceb5c1abf83 + +PCI: Enable ASPM state clearing regardless of policy + +Commit 2f671e2d allowed us to clear ASPM state when the FADT +tells us it isn't supported, but we don't put this into effect +if the aspm_policy is set to POLICY_POWERSAVE. Enable the +state to be cleared regardless of policy. + +Signed-off-by: Alex Williamson +Signed-off-by: Jesse Barnes +--- + +diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c +index eee09f7..3eb667b 100644 +--- a/drivers/pci/pcie/aspm.c ++++ b/drivers/pci/pcie/aspm.c +@@ -608,7 +608,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) + * the BIOS's expectation, we'll do so once pci_enable_device() is + * called. + */ +- if (aspm_policy != POLICY_POWERSAVE) { ++ if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) { + pcie_config_aspm_path(link); + pcie_set_clkpm(link, policy_to_clkpm_state(link)); + } From da9a09fb9144e1db312487ba4106e8ccd1f7f45a Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 28 Apr 2011 19:14:44 -0400 Subject: [PATCH 39/99] more iwlwifi fixes submitted to stable by Stanislaw --- iwl3945-disable-hw-scan-by-default.patch | 57 ++++++++ iwl3945-do-not-deprecate-software-scan.patch | 49 +++++++ ...et-tx-power-when-channel-is-changing.patch | 20 ++- iwlwifi-fix-tx_power-initialization.patch | 134 ++++++++++++++++++ kernel.spec | 13 +- 5 files changed, 265 insertions(+), 8 deletions(-) create mode 100644 iwl3945-disable-hw-scan-by-default.patch create mode 100644 iwl3945-do-not-deprecate-software-scan.patch create mode 100644 iwlwifi-fix-tx_power-initialization.patch diff --git a/iwl3945-disable-hw-scan-by-default.patch b/iwl3945-disable-hw-scan-by-default.patch new file mode 100644 index 000000000..dc612a32a --- /dev/null +++ b/iwl3945-disable-hw-scan-by-default.patch @@ -0,0 +1,57 @@ +From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:29 2011 +From: Stanislaw Gruszka +To: stable@kernel.org, kernel@lists.fedoraproject.org +Subject: [PATCH 2.6.38 3/4] iwl3945: disable hw scan by default +Date: Thu, 28 Apr 2011 14:08:14 +0200 +Message-Id: <1303992495-7337-4-git-send-email-sgruszka@redhat.com> + +commit 0263aa45293838b514b8af674a03faf040991a90 upstream. + +After new NetworkManager 0.8.996 changes, hardware scanning is causing +microcode errors as reported here: +https://bugzilla.redhat.com/show_bug.cgi?id=683571 +and sometimes kernel crashes: +https://bugzilla.redhat.com/show_bug.cgi?id=688252 + +Also with hw scan there are very bad performance on some systems +as reported here: +https://bugzilla.redhat.com/show_bug.cgi?id=671366 + +Since Intel no longer supports 3945, there is no chance to get proper +firmware fixes, we need workaround problems by disable hardware scanning +by default. + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c +index cf0699a..a8340f7 100644 +--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c ++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c +@@ -94,6 +94,7 @@ MODULE_LICENSE("GPL"); + struct iwl_mod_params iwl3945_mod_params = { + .sw_crypto = 1, + .restart_fw = 1, ++ .disable_hw_scan = 1, + /* the rest are 0 by default */ + }; + +@@ -4317,7 +4318,7 @@ MODULE_PARM_DESC(debug, "debug output mask"); + #endif + module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, + int, S_IRUGO); +-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); ++MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)"); + module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); + MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); + +-- +1.7.1 + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel + diff --git a/iwl3945-do-not-deprecate-software-scan.patch b/iwl3945-do-not-deprecate-software-scan.patch new file mode 100644 index 000000000..3fbb25261 --- /dev/null +++ b/iwl3945-do-not-deprecate-software-scan.patch @@ -0,0 +1,49 @@ +From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:23 2011 +From: Stanislaw Gruszka +To: stable@kernel.org, kernel@lists.fedoraproject.org +Subject: [PATCH 2.6.38 2/4] iwl3945: do not deprecate software scan +Date: Thu, 28 Apr 2011 14:08:13 +0200 +Message-Id: <1303992495-7337-3-git-send-email-sgruszka@redhat.com> + +commit 3bda50e3eaf58a4b9c4ce34204e5faa15c8b1b97 upstream. + +Software scanning can be used for workaround some performance problems, +so do not deprecate it. + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 ++---- + 1 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c +index 371abbf..cf0699a 100644 +--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c ++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c +@@ -3995,8 +3995,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e + * "the hard way", rather than using device's scan. + */ + if (iwl3945_mod_params.disable_hw_scan) { +- dev_printk(KERN_DEBUG, &(pdev->dev), +- "sw scan support is deprecated\n"); ++ IWL_DEBUG_INFO(priv, "Disabling hw_scan\n"); + iwl3945_hw_ops.hw_scan = NULL; + } + +@@ -4318,8 +4317,7 @@ MODULE_PARM_DESC(debug, "debug output mask"); + #endif + module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, + int, S_IRUGO); +-MODULE_PARM_DESC(disable_hw_scan, +- "disable hardware scanning (default 0) (deprecated)"); ++MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); + module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); + MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); + +-- +1.7.1 + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel + diff --git a/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch b/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch index 3583c6631..d055202a6 100644 --- a/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch +++ b/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch @@ -1,7 +1,12 @@ -From dda82c37c366672fa74499f4b639d059a802d16e Mon Sep 17 00:00:00 2001 +From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:22 2011 From: Stanislaw Gruszka -Date: Fri, 28 Jan 2011 16:47:44 +0100 -Subject: [PATCH] iwlwifi: do not set tx power when channel is changing +To: stable@kernel.org, kernel@lists.fedoraproject.org +Subject: [PATCH 2.6.38 1/4] iwlwifi: do not set tx power when channel is + changing +Date: Thu, 28 Apr 2011 14:08:12 +0200 +Message-Id: <1303992495-7337-2-git-send-email-sgruszka@redhat.com> + +commit f844a709a7d8f8be61a571afc31dfaca9e779621 upstream. Mac80211 can request for tx power and channel change in one ->config call. If that happens, *_send_tx_power functions will try to setup tx @@ -10,8 +15,6 @@ the band. I.e error "Failed to get channel info for channel 140 [0]", can be printed frequently when operating in software scanning mode. Signed-off-by: Stanislaw Gruszka -Acked-by: Wey-Yi Guy -Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- @@ -95,5 +98,10 @@ index efbde1f..91cac6f 100644 } -- -1.7.4.4 +1.7.1 + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel diff --git a/iwlwifi-fix-tx_power-initialization.patch b/iwlwifi-fix-tx_power-initialization.patch new file mode 100644 index 000000000..5103d3f55 --- /dev/null +++ b/iwlwifi-fix-tx_power-initialization.patch @@ -0,0 +1,134 @@ +From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:35 2011 +From: Stanislaw Gruszka +To: stable@kernel.org, kernel@lists.fedoraproject.org +Subject: [PATCH 2.6.38 4/4] iwlwifi: fix tx_power initialization +Date: Thu, 28 Apr 2011 14:08:15 +0200 +Message-Id: <1303992495-7337-5-git-send-email-sgruszka@redhat.com> + +commit 332704a51498a7e29aa92c19dc03f11f80b71bfe upstream. + +priv->tx_power_next is not initialized to max supported power, +but instead default value is used, what cause errors like + +[ 58.597834] iwl3945 0000:03:00.0: Requested user TXPOWER 15 above upper limit 14. +[ 58.597839] iwl3945 0000:03:00.0: Error setting Tx power (-22). + +if maximum tx power read from the eeprom is smaller than default. +In consequence card is unable to initialize properly. Fix the problem +and cleanup tx power initialization. + +Reported-and-tested-by: Robin Dong +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 -- + drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ------ + drivers/net/wireless/iwlwifi/iwl-core.c | 9 +++++++-- + drivers/net/wireless/iwlwifi/iwl-eeprom.c | 7 ------- + drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ---- + 5 files changed, 7 insertions(+), 21 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +index 65b5834..c2dd4cd 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h ++++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +@@ -74,8 +74,6 @@ + /* RSSI to dBm */ + #define IWL39_RSSI_OFFSET 95 + +-#define IWL_DEFAULT_TX_POWER 0x0F +- + /* + * EEPROM related constants, enums, and structures. + */ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c +index c1cfd99..35239f0 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -3841,12 +3841,6 @@ static int iwl_init_drv(struct iwl_priv *priv) + priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; + } + +- /* Set the tx_power_user_lmt to the lowest power level +- * this value will get overwritten by channel max power avg +- * from eeprom */ +- priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; +- priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN; +- + ret = iwl_init_channel_map(priv); + if (ret) { + IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); +diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c +index 91cac6f..294e9fc 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-core.c ++++ b/drivers/net/wireless/iwlwifi/iwl-core.c +@@ -168,6 +168,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) + struct ieee80211_channel *geo_ch; + struct ieee80211_rate *rates; + int i = 0; ++ s8 max_tx_power = 0; + + if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || + priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { +@@ -244,8 +245,8 @@ int iwlcore_init_geos(struct iwl_priv *priv) + + geo_ch->flags |= ch->ht40_extension_channel; + +- if (ch->max_power_avg > priv->tx_power_device_lmt) +- priv->tx_power_device_lmt = ch->max_power_avg; ++ if (ch->max_power_avg > max_tx_power) ++ max_tx_power = ch->max_power_avg; + } else { + geo_ch->flags |= IEEE80211_CHAN_DISABLED; + } +@@ -258,6 +259,10 @@ int iwlcore_init_geos(struct iwl_priv *priv) + geo_ch->flags); + } + ++ priv->tx_power_device_lmt = max_tx_power; ++ priv->tx_power_user_lmt = max_tx_power; ++ priv->tx_power_next = max_tx_power; ++ + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && + priv->cfg->sku & IWL_SKU_A) { + IWL_INFO(priv, "Incorrectly detected BG card as ABG. " +diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c +index 358cfd7..8b3c127 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c ++++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c +@@ -724,13 +724,6 @@ int iwl_init_channel_map(struct iwl_priv *priv) + flags & EEPROM_CHANNEL_RADAR)) + ? "" : "not "); + +- /* Set the tx_power_user_lmt to the highest power +- * supported by any channel */ +- if (eeprom_ch_info[ch].max_power_avg > +- priv->tx_power_user_lmt) +- priv->tx_power_user_lmt = +- eeprom_ch_info[ch].max_power_avg; +- + ch_info++; + } + } +diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c +index a8340f7..64917ed 100644 +--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c ++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c +@@ -3859,10 +3859,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) + priv->force_reset[IWL_FW_RESET].reset_duration = + IWL_DELAY_NEXT_FORCE_FW_RELOAD; + +- +- priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; +- priv->tx_power_next = IWL_DEFAULT_TX_POWER; +- + if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { + IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", + eeprom->version); +-- +1.7.1 + +_______________________________________________ +kernel mailing list +kernel@lists.fedoraproject.org +https://admin.fedoraproject.org/mailman/listinfo/kernel + diff --git a/kernel.spec b/kernel.spec index 98df4ba32..74494ab64 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 19 +%global baserelease 20 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -727,7 +727,10 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch -Patch12307: iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch +Patch12310: iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch +Patch12311: iwl3945-do-not-deprecate-software-scan.patch +Patch12312: iwl3945-disable-hw-scan-by-default.patch +Patch12313: iwlwifi-fix-tx_power-initialization.patch #netconsole fixes Patch12400: linux-2.6-netconsole-deadlock.patch @@ -1258,6 +1261,9 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # rhbz#688252 ApplyPatch iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch +ApplyPatch iwl3945-do-not-deprecate-software-scan.patch +ApplyPatch iwl3945-disable-hw-scan-by-default.patch +ApplyPatch iwlwifi-fix-tx_power-initialization.patch # Misc fixes # The input layer spews crap no-one cares about. @@ -1966,6 +1972,9 @@ fi # and build. %changelog +* Thu Apr 28 2011 Kyle McMartin 2.6.38.4-20 +- [sgruszka@] Upstream fixes for iwl3945 bugs (#683571, #688252, #671366) + * Tue Apr 26 2011 Chuck Ebbert - Another fix for ASPM powersave mode From 19b3eb0b8a247db293f482107da7753b63bbe098 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 1 May 2011 23:11:33 -0400 Subject: [PATCH 40/99] update to stable rc 2.6.38.5-rc1 --- ...e-sysfs-files-from-a-resume-notifier.patch | 91 ------------ flexcop-fix-xlate_proc_name-warning.patch | 30 ---- iwl3945-disable-hw-scan-by-default.patch | 57 -------- iwl3945-do-not-deprecate-software-scan.patch | 49 ------- ...et-tx-power-when-channel-is-changing.patch | 107 -------------- iwlwifi-fix-tx_power-initialization.patch | 134 ------------------ kernel.spec | 28 +--- sources | 1 + 8 files changed, 7 insertions(+), 490 deletions(-) delete mode 100644 acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch delete mode 100644 flexcop-fix-xlate_proc_name-warning.patch delete mode 100644 iwl3945-disable-hw-scan-by-default.patch delete mode 100644 iwl3945-do-not-deprecate-software-scan.patch delete mode 100644 iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch delete mode 100644 iwlwifi-fix-tx_power-initialization.patch diff --git a/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch b/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch deleted file mode 100644 index ace336b47..000000000 --- a/acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch +++ /dev/null @@ -1,91 +0,0 @@ -From lenb@kernel.org Wed Mar 23 03:07:45 2011 -From: Len Brown -To: linux-acpi@vger.kernel.org -Cc: Kyle McMartin , Len Brown -Subject: [PATCH 35/42] ACPI battery: fribble sysfs files from a resume notifier -Date: Wed, 23 Mar 2011 02:42:48 -0400 - -From: Kyle McMartin - -Upstream commit 25be5821521640eb00b7eb219ffe59664510d073 - -Commit da8aeb92 re-poked the battery on resume, but Linus reports that -it broke his eee and partially reverted it in b23fffd7. Unfortunately -this also results in my x201s giving crack values until the sysfs files -are poked again. In the revert message, it was suggested that we poke it -from a PM notifier, so let's do that. - -With this in place, I haven't noticed the units going nutty on my -gnome-power-manager across a dozen suspends or so... - -Signed-off-by: Kyle McMartin -Acked-by: Rafael J. Wysocki -Signed-off-by: Len Brown ---- - drivers/acpi/battery.c | 22 ++++++++++++++++++++++ - 1 files changed, 22 insertions(+), 0 deletions(-) - -diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c -index ac1a599..fcc13ac 100644 ---- a/drivers/acpi/battery.c -+++ b/drivers/acpi/battery.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - - #ifdef CONFIG_ACPI_PROCFS_POWER - #include -@@ -102,6 +103,7 @@ struct acpi_battery { - struct mutex lock; - struct power_supply bat; - struct acpi_device *device; -+ struct notifier_block pm_nb; - unsigned long update_time; - int rate_now; - int capacity_now; -@@ -940,6 +942,21 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event) - power_supply_changed(&battery->bat); - } - -+static int battery_notify(struct notifier_block *nb, -+ unsigned long mode, void *_unused) -+{ -+ struct acpi_battery *battery = container_of(nb, struct acpi_battery, -+ pm_nb); -+ switch (mode) { -+ case PM_POST_SUSPEND: -+ sysfs_remove_battery(battery); -+ sysfs_add_battery(battery); -+ break; -+ } -+ -+ return 0; -+} -+ - static int acpi_battery_add(struct acpi_device *device) - { - int result = 0; -@@ -972,6 +989,10 @@ static int acpi_battery_add(struct acpi_device *device) - #endif - kfree(battery); - } -+ -+ battery->pm_nb.notifier_call = battery_notify; -+ register_pm_notifier(&battery->pm_nb); -+ - return result; - } - -@@ -982,6 +1003,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) - if (!device || !acpi_driver_data(device)) - return -EINVAL; - battery = acpi_driver_data(device); -+ unregister_pm_notifier(&battery->pm_nb); - #ifdef CONFIG_ACPI_PROCFS_POWER - acpi_battery_remove_fs(device); - #endif --- -1.7.4.1.343.ga91df - diff --git a/flexcop-fix-xlate_proc_name-warning.patch b/flexcop-fix-xlate_proc_name-warning.patch deleted file mode 100644 index 82b50a47f..000000000 --- a/flexcop-fix-xlate_proc_name-warning.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c -index 227c020..7465308 100644 ---- a/drivers/media/dvb/b2c2/flexcop-pci.c -+++ b/drivers/media/dvb/b2c2/flexcop-pci.c -@@ -39,6 +39,7 @@ MODULE_PARM_DESC(debug, - - #define DRIVER_VERSION "0.1" - #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver" -+#define FLEXCOP_MODULE_NAME "b2c2-flexcop" - #define DRIVER_AUTHOR "Patrick Boettcher " - - struct flexcop_pci { -@@ -299,7 +300,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) - return ret; - pci_set_master(fc_pci->pdev); - -- if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0) -+ if ((ret = pci_request_regions(fc_pci->pdev, FLEXCOP_MODULE_NAME)) != 0) - goto err_pci_disable_device; - - fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800); -@@ -313,7 +314,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) - pci_set_drvdata(fc_pci->pdev, fc_pci); - spin_lock_init(&fc_pci->irq_lock); - if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr, -- IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) -+ IRQF_SHARED, FLEXCOP_MODULE_NAME, fc_pci)) != 0) - goto err_pci_iounmap; - - fc_pci->init_state |= FC_PCI_INIT; diff --git a/iwl3945-disable-hw-scan-by-default.patch b/iwl3945-disable-hw-scan-by-default.patch deleted file mode 100644 index dc612a32a..000000000 --- a/iwl3945-disable-hw-scan-by-default.patch +++ /dev/null @@ -1,57 +0,0 @@ -From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:29 2011 -From: Stanislaw Gruszka -To: stable@kernel.org, kernel@lists.fedoraproject.org -Subject: [PATCH 2.6.38 3/4] iwl3945: disable hw scan by default -Date: Thu, 28 Apr 2011 14:08:14 +0200 -Message-Id: <1303992495-7337-4-git-send-email-sgruszka@redhat.com> - -commit 0263aa45293838b514b8af674a03faf040991a90 upstream. - -After new NetworkManager 0.8.996 changes, hardware scanning is causing -microcode errors as reported here: -https://bugzilla.redhat.com/show_bug.cgi?id=683571 -and sometimes kernel crashes: -https://bugzilla.redhat.com/show_bug.cgi?id=688252 - -Also with hw scan there are very bad performance on some systems -as reported here: -https://bugzilla.redhat.com/show_bug.cgi?id=671366 - -Since Intel no longer supports 3945, there is no chance to get proper -firmware fixes, we need workaround problems by disable hardware scanning -by default. - -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c -index cf0699a..a8340f7 100644 ---- a/drivers/net/wireless/iwlwifi/iwl3945-base.c -+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c -@@ -94,6 +94,7 @@ MODULE_LICENSE("GPL"); - struct iwl_mod_params iwl3945_mod_params = { - .sw_crypto = 1, - .restart_fw = 1, -+ .disable_hw_scan = 1, - /* the rest are 0 by default */ - }; - -@@ -4317,7 +4318,7 @@ MODULE_PARM_DESC(debug, "debug output mask"); - #endif - module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, - int, S_IRUGO); --MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); -+MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)"); - module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); - MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); - --- -1.7.1 - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel - diff --git a/iwl3945-do-not-deprecate-software-scan.patch b/iwl3945-do-not-deprecate-software-scan.patch deleted file mode 100644 index 3fbb25261..000000000 --- a/iwl3945-do-not-deprecate-software-scan.patch +++ /dev/null @@ -1,49 +0,0 @@ -From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:23 2011 -From: Stanislaw Gruszka -To: stable@kernel.org, kernel@lists.fedoraproject.org -Subject: [PATCH 2.6.38 2/4] iwl3945: do not deprecate software scan -Date: Thu, 28 Apr 2011 14:08:13 +0200 -Message-Id: <1303992495-7337-3-git-send-email-sgruszka@redhat.com> - -commit 3bda50e3eaf58a4b9c4ce34204e5faa15c8b1b97 upstream. - -Software scanning can be used for workaround some performance problems, -so do not deprecate it. - -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 ++---- - 1 files changed, 2 insertions(+), 4 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c -index 371abbf..cf0699a 100644 ---- a/drivers/net/wireless/iwlwifi/iwl3945-base.c -+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c -@@ -3995,8 +3995,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e - * "the hard way", rather than using device's scan. - */ - if (iwl3945_mod_params.disable_hw_scan) { -- dev_printk(KERN_DEBUG, &(pdev->dev), -- "sw scan support is deprecated\n"); -+ IWL_DEBUG_INFO(priv, "Disabling hw_scan\n"); - iwl3945_hw_ops.hw_scan = NULL; - } - -@@ -4318,8 +4317,7 @@ MODULE_PARM_DESC(debug, "debug output mask"); - #endif - module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, - int, S_IRUGO); --MODULE_PARM_DESC(disable_hw_scan, -- "disable hardware scanning (default 0) (deprecated)"); -+MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); - module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); - MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); - --- -1.7.1 - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel - diff --git a/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch b/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch deleted file mode 100644 index d055202a6..000000000 --- a/iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch +++ /dev/null @@ -1,107 +0,0 @@ -From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:22 2011 -From: Stanislaw Gruszka -To: stable@kernel.org, kernel@lists.fedoraproject.org -Subject: [PATCH 2.6.38 1/4] iwlwifi: do not set tx power when channel is - changing -Date: Thu, 28 Apr 2011 14:08:12 +0200 -Message-Id: <1303992495-7337-2-git-send-email-sgruszka@redhat.com> - -commit f844a709a7d8f8be61a571afc31dfaca9e779621 upstream. - -Mac80211 can request for tx power and channel change in one ->config -call. If that happens, *_send_tx_power functions will try to setup tx -power for old channel, what can be not correct because we already change -the band. I.e error "Failed to get channel info for channel 140 [0]", -can be printed frequently when operating in software scanning mode. - -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- - drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 5 ++--- - drivers/net/wireless/iwlwifi/iwl-core.c | 13 ++++++++++--- - 4 files changed, 14 insertions(+), 8 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c -index 39b6f16..4e7b58b 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-3945.c -+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c -@@ -1823,7 +1823,7 @@ int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ -- rc = priv->cfg->ops->lib->send_tx_power(priv); -+ rc = iwl_set_tx_power(priv, priv->tx_power_next, true); - if (rc) { - IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); - return rc; -diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c -index 91a9f52..992caa0 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-4965.c -+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c -@@ -1571,7 +1571,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ -- ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); -+ ret = iwl_set_tx_power(priv, priv->tx_power_next, true); - if (ret) { - IWL_ERR(priv, "Error sending TX power (%d)\n", ret); - return ret; -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index 6d140bd..ee802fe 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -288,10 +288,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) - * If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames. - * -- * FIXME: which RXON requires a tune? Can we optimise this out in -- * some cases? -+ * It's expected we set power here if channel is changing. - */ -- ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); -+ ret = iwl_set_tx_power(priv, priv->tx_power_next, true); - if (ret) { - IWL_ERR(priv, "Error sending TX power (%d)\n", ret); - return ret; -diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c -index efbde1f..91cac6f 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-core.c -+++ b/drivers/net/wireless/iwlwifi/iwl-core.c -@@ -1161,6 +1161,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) - { - int ret; - s8 prev_tx_power; -+ bool defer; -+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - - lockdep_assert_held(&priv->mutex); - -@@ -1188,10 +1190,15 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) - if (!iwl_is_ready_rf(priv)) - return -EIO; - -- /* scan complete use tx_power_next, need to be updated */ -+ /* scan complete and commit_rxon use tx_power_next value, -+ * it always need to be updated for newest request */ - priv->tx_power_next = tx_power; -- if (test_bit(STATUS_SCANNING, &priv->status) && !force) { -- IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n"); -+ -+ /* do not set tx power when scanning or channel changing */ -+ defer = test_bit(STATUS_SCANNING, &priv->status) || -+ memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); -+ if (defer && !force) { -+ IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); - return 0; - } - --- -1.7.1 - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel - diff --git a/iwlwifi-fix-tx_power-initialization.patch b/iwlwifi-fix-tx_power-initialization.patch deleted file mode 100644 index 5103d3f55..000000000 --- a/iwlwifi-fix-tx_power-initialization.patch +++ /dev/null @@ -1,134 +0,0 @@ -From kernel-bounces@lists.fedoraproject.org Thu Apr 28 08:09:35 2011 -From: Stanislaw Gruszka -To: stable@kernel.org, kernel@lists.fedoraproject.org -Subject: [PATCH 2.6.38 4/4] iwlwifi: fix tx_power initialization -Date: Thu, 28 Apr 2011 14:08:15 +0200 -Message-Id: <1303992495-7337-5-git-send-email-sgruszka@redhat.com> - -commit 332704a51498a7e29aa92c19dc03f11f80b71bfe upstream. - -priv->tx_power_next is not initialized to max supported power, -but instead default value is used, what cause errors like - -[ 58.597834] iwl3945 0000:03:00.0: Requested user TXPOWER 15 above upper limit 14. -[ 58.597839] iwl3945 0000:03:00.0: Error setting Tx power (-22). - -if maximum tx power read from the eeprom is smaller than default. -In consequence card is unable to initialize properly. Fix the problem -and cleanup tx power initialization. - -Reported-and-tested-by: Robin Dong -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 -- - drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ------ - drivers/net/wireless/iwlwifi/iwl-core.c | 9 +++++++-- - drivers/net/wireless/iwlwifi/iwl-eeprom.c | 7 ------- - drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ---- - 5 files changed, 7 insertions(+), 21 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h -index 65b5834..c2dd4cd 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h -+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h -@@ -74,8 +74,6 @@ - /* RSSI to dBm */ - #define IWL39_RSSI_OFFSET 95 - --#define IWL_DEFAULT_TX_POWER 0x0F -- - /* - * EEPROM related constants, enums, and structures. - */ -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c -index c1cfd99..35239f0 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -3841,12 +3841,6 @@ static int iwl_init_drv(struct iwl_priv *priv) - priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; - } - -- /* Set the tx_power_user_lmt to the lowest power level -- * this value will get overwritten by channel max power avg -- * from eeprom */ -- priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; -- priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN; -- - ret = iwl_init_channel_map(priv); - if (ret) { - IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); -diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c -index 91cac6f..294e9fc 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-core.c -+++ b/drivers/net/wireless/iwlwifi/iwl-core.c -@@ -168,6 +168,7 @@ int iwlcore_init_geos(struct iwl_priv *priv) - struct ieee80211_channel *geo_ch; - struct ieee80211_rate *rates; - int i = 0; -+ s8 max_tx_power = 0; - - if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || - priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { -@@ -244,8 +245,8 @@ int iwlcore_init_geos(struct iwl_priv *priv) - - geo_ch->flags |= ch->ht40_extension_channel; - -- if (ch->max_power_avg > priv->tx_power_device_lmt) -- priv->tx_power_device_lmt = ch->max_power_avg; -+ if (ch->max_power_avg > max_tx_power) -+ max_tx_power = ch->max_power_avg; - } else { - geo_ch->flags |= IEEE80211_CHAN_DISABLED; - } -@@ -258,6 +259,10 @@ int iwlcore_init_geos(struct iwl_priv *priv) - geo_ch->flags); - } - -+ priv->tx_power_device_lmt = max_tx_power; -+ priv->tx_power_user_lmt = max_tx_power; -+ priv->tx_power_next = max_tx_power; -+ - if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && - priv->cfg->sku & IWL_SKU_A) { - IWL_INFO(priv, "Incorrectly detected BG card as ABG. " -diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c -index 358cfd7..8b3c127 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c -+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c -@@ -724,13 +724,6 @@ int iwl_init_channel_map(struct iwl_priv *priv) - flags & EEPROM_CHANNEL_RADAR)) - ? "" : "not "); - -- /* Set the tx_power_user_lmt to the highest power -- * supported by any channel */ -- if (eeprom_ch_info[ch].max_power_avg > -- priv->tx_power_user_lmt) -- priv->tx_power_user_lmt = -- eeprom_ch_info[ch].max_power_avg; -- - ch_info++; - } - } -diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c -index a8340f7..64917ed 100644 ---- a/drivers/net/wireless/iwlwifi/iwl3945-base.c -+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c -@@ -3859,10 +3859,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) - priv->force_reset[IWL_FW_RESET].reset_duration = - IWL_DELAY_NEXT_FORCE_FW_RELOAD; - -- -- priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; -- priv->tx_power_next = IWL_DEFAULT_TX_POWER; -- - if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { - IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", - eeprom->version); --- -1.7.1 - -_______________________________________________ -kernel mailing list -kernel@lists.fedoraproject.org -https://admin.fedoraproject.org/mailman/listinfo/kernel - diff --git a/kernel.spec b/kernel.spec index 74494ab64..d54b809f9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 20 +%global baserelease 21 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,9 +63,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 4 +%define stable_update 5 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -644,8 +644,6 @@ Patch391: linux-2.6-acpi-video-dos.patch Patch393: acpi-ec-add-delay-before-write.patch Patch394: linux-2.6-acpi-debug-infinite-loop.patch -Patch399: acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch - Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch @@ -700,8 +698,6 @@ Patch2899: linux-2.6-v4l-dvb-fixes.patch Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch -Patch2918: flexcop-fix-xlate_proc_name-warning.patch - # fs fixes # NFSv4 @@ -727,11 +723,6 @@ Patch12303: dmar-disable-when-ricoh-multifunction.patch Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch -Patch12310: iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch -Patch12311: iwl3945-do-not-deprecate-software-scan.patch -Patch12312: iwl3945-disable-hw-scan-by-default.patch -Patch12313: iwlwifi-fix-tx_power-initialization.patch - #netconsole fixes Patch12400: linux-2.6-netconsole-deadlock.patch @@ -1226,7 +1217,6 @@ ApplyPatch linux-2.6-defaults-acpi-video.patch ApplyPatch linux-2.6-acpi-video-dos.patch ApplyPatch acpi-ec-add-delay-before-write.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch -ApplyPatch acpi_battery-fribble-sysfs-files-from-a-resume-notifier.patch # Various low-impact patches to aid debugging. ApplyPatch linux-2.6-debug-sizeof-structs.patch @@ -1259,12 +1249,6 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Networking -# rhbz#688252 -ApplyPatch iwlwifi-do-not-set-tx-power-when-channel-is-changing.patch -ApplyPatch iwl3945-do-not-deprecate-software-scan.patch -ApplyPatch iwl3945-disable-hw-scan-by-default.patch -ApplyPatch iwlwifi-fix-tx_power-initialization.patch - # Misc fixes # The input layer spews crap no-one cares about. ApplyPatch linux-2.6-input-kill-stupid-messages.patch @@ -1332,9 +1316,6 @@ ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch -# rhbz#664852 -ApplyPatch flexcop-fix-xlate_proc_name-warning.patch - # Patches headed upstream ApplyPatch disable-i8042-check-on-apple-mac.patch @@ -1972,6 +1953,9 @@ fi # and build. %changelog +* Sun May 01 2011 Kyle McMartin 2.6.38.5-21.rc1 +- Update to stable release candidate 2.6.38.5-rc1 + * Thu Apr 28 2011 Kyle McMartin 2.6.38.4-20 - [sgruszka@] Upstream fixes for iwl3945 bugs (#683571, #688252, #671366) diff --git a/sources b/sources index b9a628517..f1161f29e 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 6ef1279c7bd0078fc0fd50aa83e86203 patch-2.6.38.4.bz2 +12b510d6afa32d74a1c7b6aedf54edf5 patch-2.6.38.5-rc1.bz2 From 410297116401a1ef99c56ee871053ddca671be70 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 2 May 2011 15:04:10 -0400 Subject: [PATCH 41/99] update to released 2.6.38.5 --- kernel.spec | 11 +++++++---- sources | 3 +-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel.spec b/kernel.spec index d54b809f9..4b1898aa0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 21 +%global baserelease 22 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -65,7 +65,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 5 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -82,9 +82,9 @@ Summary: The Linux kernel # The next upstream release sublevel (base_sublevel+1) %define upstream_sublevel %(echo $((%{base_sublevel} + 1))) # The rc snapshot level -%define rcrev 8 +%define rcrev 0 # The git snapshot level -%define gitrev 4 +%define gitrev 0 # Set rpm version accordingly %define rpmversion 2.6.%{upstream_sublevel} %endif @@ -1953,6 +1953,9 @@ fi # and build. %changelog +* Mon May 02 2011 Kyle McMartin 2.6.38.5-22 +- And to the released 2.6.38.5 + * Sun May 01 2011 Kyle McMartin 2.6.38.5-21.rc1 - Update to stable release candidate 2.6.38.5-rc1 diff --git a/sources b/sources index f1161f29e..12ff2148e 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -6ef1279c7bd0078fc0fd50aa83e86203 patch-2.6.38.4.bz2 -12b510d6afa32d74a1c7b6aedf54edf5 patch-2.6.38.5-rc1.bz2 +c8f233d1d31030eb019ab391071e65c2 patch-2.6.38.5.bz2 From 6034fb773e28ddc0540dfd809d82728b52543532 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 2 May 2011 18:30:35 -0400 Subject: [PATCH 42/99] [SCSI] mpt2sas: prevent heap overflows and unchecked reads --- kernel.spec | 10 +++ ...t-heap-overflows-and-unchecked-reads.patch | 83 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch diff --git a/kernel.spec b/kernel.spec index 4b1898aa0..b92634dd9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -726,6 +726,9 @@ Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch #netconsole fixes Patch12400: linux-2.6-netconsole-deadlock.patch +# CVE-2011-1494, CVE-2011-1495 +Patch12401: scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1345,6 +1348,9 @@ ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch #rhbz 668231 ApplyPatch linux-2.6-netconsole-deadlock.patch +# CVE-2011-1494, CVE-2011-1495 +ApplyPatch scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch + # END OF PATCH APPLICATIONS %endif @@ -1953,6 +1959,10 @@ fi # and build. %changelog +* Mon May 02 2011 Chuck Ebbert +- [SCSI] mpt2sas: prevent heap overflows and unchecked reads + (CVE-2011-1494, CVE-2011-1495) + * Mon May 02 2011 Kyle McMartin 2.6.38.5-22 - And to the released 2.6.38.5 diff --git a/scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch b/scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch new file mode 100644 index 000000000..1803cf84f --- /dev/null +++ b/scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch @@ -0,0 +1,83 @@ +From: Dan Rosenberg +Date: Tue, 5 Apr 2011 16:45:59 +0000 (-0400) +Subject: [SCSI] mpt2sas: prevent heap overflows and unchecked reads +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=a1f74ae82d133ebb2aabb19d181944b4e83e9960 + +[SCSI] mpt2sas: prevent heap overflows and unchecked reads + +At two points in handling device ioctls via /dev/mpt2ctl, user-supplied +length values are used to copy data from userspace into heap buffers +without bounds checking, allowing controllable heap corruption and +subsequently privilege escalation. + +Additionally, user-supplied values are used to determine the size of a +copy_to_user() as well as the offset into the buffer to be read, with no +bounds checking, allowing users to read arbitrary kernel memory. + +Signed-off-by: Dan Rosenberg +Cc: stable@kernel.org +Acked-by: Eric Moore +Signed-off-by: James Bottomley +--- + +diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c +index 1c6d2b4..d72f1f2 100644 +--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c ++++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c +@@ -688,6 +688,13 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, + goto out; + } + ++ /* Check for overflow and wraparound */ ++ if (karg.data_sge_offset * 4 > ioc->request_sz || ++ karg.data_sge_offset > (UINT_MAX / 4)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ + /* copy in request message frame from user */ + if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, +@@ -1963,7 +1970,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) + Mpi2DiagBufferPostReply_t *mpi_reply; + int rc, i; + u8 buffer_type; +- unsigned long timeleft; ++ unsigned long timeleft, request_size, copy_size; + u16 smid; + u16 ioc_status; + u8 issue_reset = 0; +@@ -1999,6 +2006,8 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) + return -ENOMEM; + } + ++ request_size = ioc->diag_buffer_sz[buffer_type]; ++ + if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { + printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " + "or bytes_to_read are not 4 byte aligned\n", ioc->name, +@@ -2006,13 +2015,23 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) + return -EINVAL; + } + ++ if (karg.starting_offset > request_size) ++ return -EINVAL; ++ + diag_data = (void *)(request_data + karg.starting_offset); + dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " + "offset(%d), sz(%d)\n", ioc->name, __func__, + diag_data, karg.starting_offset, karg.bytes_to_read)); + ++ /* Truncate data on requests that are too large */ ++ if ((diag_data + karg.bytes_to_read < diag_data) || ++ (diag_data + karg.bytes_to_read > request_data + request_size)) ++ copy_size = request_size - karg.starting_offset; ++ else ++ copy_size = karg.bytes_to_read; ++ + if (copy_to_user((void __user *)uarg->diagnostic_data, +- diag_data, karg.bytes_to_read)) { ++ diag_data, copy_size)) { + printk(MPT2SAS_ERR_FMT "%s: Unable to write " + "mpt_diag_read_buffer_t data @ %p\n", ioc->name, + __func__, diag_data); From e883ed16c1e91e1d719affc4fdad8f5803751432 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 2 May 2011 18:47:44 -0400 Subject: [PATCH 43/99] bonding: Incorrect TX queue offset (CVE-2011-1581) --- bonding-incorrect-tx-queue-offset.patch | 54 +++++++++++++++++++++++++ kernel.spec | 7 ++++ 2 files changed, 61 insertions(+) create mode 100644 bonding-incorrect-tx-queue-offset.patch diff --git a/bonding-incorrect-tx-queue-offset.patch b/bonding-incorrect-tx-queue-offset.patch new file mode 100644 index 000000000..ebc33de4f --- /dev/null +++ b/bonding-incorrect-tx-queue-offset.patch @@ -0,0 +1,54 @@ +From: Phil Oester +Date: Mon, 14 Mar 2011 06:22:04 +0000 (+0000) +Subject: bonding: Incorrect TX queue offset +X-Git-Tag: v2.6.39-rc1~468^2~15 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=fd0e435b0fe85622f167b84432552885a4856ac8 + +bonding: Incorrect TX queue offset + +When packets come in from a device with >= 16 receive queues +headed out a bonding interface, syslog gets filled with this: + + kernel: bond0 selects TX queue 16, but real number of TX queues is 16 + +because queue_mapping is offset by 1. Adjust return value +to account for the offset. + +This is a revision of my earlier patch (which did not use the +skb_rx_queue_* helpers - thanks to Ben for the suggestion). +Andy submitted a similar patch which emits a pr_warning on +invalid queue selection, but I believe the log spew is +not useful. We can revisit that question in the future, +but in the interim I believe fixing the core problem is +worthwhile. + +Signed-off-by: Phil Oester +Signed-off-by: Andy Gospodarek +Signed-off-by: David S. Miller +--- + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 3ad4f50..a93d941 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -4341,11 +4341,18 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) + { + /* + * This helper function exists to help dev_pick_tx get the correct +- * destination queue. Using a helper function skips the a call to ++ * destination queue. Using a helper function skips a call to + * skb_tx_hash and will put the skbs in the queue we expect on their + * way down to the bonding driver. + */ +- return skb->queue_mapping; ++ u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0; ++ ++ if (unlikely(txq >= dev->real_num_tx_queues)) { ++ do ++ txq -= dev->real_num_tx_queues; ++ while (txq >= dev->real_num_tx_queues); ++ } ++ return txq; + } + + static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/kernel.spec b/kernel.spec index b92634dd9..a36c747fc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -729,6 +729,9 @@ Patch12400: linux-2.6-netconsole-deadlock.patch # CVE-2011-1494, CVE-2011-1495 Patch12401: scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch +# CVE-2011-1581 +Patch12402: bonding-incorrect-tx-queue-offset.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1351,6 +1354,9 @@ ApplyPatch linux-2.6-netconsole-deadlock.patch # CVE-2011-1494, CVE-2011-1495 ApplyPatch scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch +# CVE-2011-1581 +ApplyPatch bonding-incorrect-tx-queue-offset.patch + # END OF PATCH APPLICATIONS %endif @@ -1962,6 +1968,7 @@ fi * Mon May 02 2011 Chuck Ebbert - [SCSI] mpt2sas: prevent heap overflows and unchecked reads (CVE-2011-1494, CVE-2011-1495) +- bonding: Incorrect TX queue offset (CVE-2011-1581) * Mon May 02 2011 Kyle McMartin 2.6.38.5-22 - And to the released 2.6.38.5 From 50ffc6fec51e26b67f3aa57fb26914c04af6f8f9 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 3 May 2011 02:38:59 -0400 Subject: [PATCH 44/99] Restore reliable stack backtraces, and hopefully fix RHBZ #700718 --- kernel.spec | 8 + ...info-when-frame-pointer-is-available.patch | 352 ++++++++++++++++++ 2 files changed, 360 insertions(+) create mode 100644 x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch diff --git a/kernel.spec b/kernel.spec index a36c747fc..233f78229 100644 --- a/kernel.spec +++ b/kernel.spec @@ -732,6 +732,10 @@ Patch12401: scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch # CVE-2011-1581 Patch12402: bonding-incorrect-tx-queue-offset.patch +# Restore reliable stack backtraces, and hopefully +# fix RHBZ #700718 +Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1179,6 +1183,9 @@ ApplyPatch linux-2.6-utrace-ptrace.patch # Architecture patches # x86(-64) +# Restore reliable stack backtraces, and hopefully +# fix RHBZ #700718 +ApplyPatch x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch # # Intel IOMMU @@ -1969,6 +1976,7 @@ fi - [SCSI] mpt2sas: prevent heap overflows and unchecked reads (CVE-2011-1494, CVE-2011-1495) - bonding: Incorrect TX queue offset (CVE-2011-1581) +- Restore reliable stack backtraces, and hopefully fix RHBZ #700718 * Mon May 02 2011 Kyle McMartin 2.6.38.5-22 - And to the released 2.6.38.5 diff --git a/x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch b/x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch new file mode 100644 index 000000000..36eae4b97 --- /dev/null +++ b/x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch @@ -0,0 +1,352 @@ +From: Namhyung Kim +Date: Fri, 18 Mar 2011 02:40:06 +0000 (+0900) +Subject: x86, dumpstack: Correct stack dump info when frame pointer is available +X-Git-Tag: v2.6.39-rc1~64^2~7 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=e8e999cf3cc733482e390b02ff25a64cecdc0b64 + +x86, dumpstack: Correct stack dump info when frame pointer is available + +Current stack dump code scans entire stack and check each entry +contains a pointer to kernel code. If CONFIG_FRAME_POINTER=y it +could mark whether the pointer is valid or not based on value of +the frame pointer. Invalid entries could be preceded by '?' sign. + +However this was not going to happen because scan start point +was always higher than the frame pointer so that they could not +meet. + +Commit 9c0729dc8062 ("x86: Eliminate bp argument from the stack +tracing routines") delayed bp acquisition point, so the bp was +read in lower frame, thus all of the entries were marked +invalid. + +This patch fixes this by reverting above commit while retaining +stack_frame() helper as suggested by Frederic Weisbecker. + +End result looks like below: + +before: + + [ 3.508329] Call Trace: + [ 3.508551] [] ? panic+0x91/0x199 + [ 3.508662] [] ? printk+0x68/0x6a + [ 3.508770] [] ? mount_block_root+0x257/0x26e + [ 3.508876] [] ? mount_root+0x56/0x5a + [ 3.508975] [] ? prepare_namespace+0x170/0x1a9 + [ 3.509216] [] ? kernel_init+0x1d2/0x1e2 + [ 3.509335] [] ? kernel_thread_helper+0x4/0x10 + [ 3.509442] [] ? restore_args+0x0/0x30 + [ 3.509542] [] ? kernel_init+0x0/0x1e2 + [ 3.509641] [] ? kernel_thread_helper+0x0/0x10 + +after: + + [ 3.522991] Call Trace: + [ 3.523351] [] panic+0x91/0x199 + [ 3.523468] [] ? printk+0x68/0x6a + [ 3.523576] [] mount_block_root+0x257/0x26e + [ 3.523681] [] mount_root+0x56/0x5a + [ 3.523780] [] prepare_namespace+0x170/0x1a9 + [ 3.523885] [] kernel_init+0x1d2/0x1e2 + [ 3.523987] [] kernel_thread_helper+0x4/0x10 + [ 3.524228] [] ? restore_args+0x0/0x30 + [ 3.524345] [] ? kernel_init+0x0/0x1e2 + [ 3.524445] [] ? kernel_thread_helper+0x0/0x10 + + -v5: + * fix build breakage with oprofile + + -v4: + * use 0 instead of regs->bp + * separate out printk changes + + -v3: + * apply comment from Frederic + * add a couple of printk fixes + +Signed-off-by: Namhyung Kim +Acked-by: Peter Zijlstra +Acked-by: Frederic Weisbecker +Cc: Soren Sandmann +Cc: Paul Mackerras +Cc: Arnaldo Carvalho de Melo +Cc: Robert Richter +LKML-Reference: <1300416006-3163-1-git-send-email-namhyung@gmail.com> +Signed-off-by: Ingo Molnar +--- + +diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h +index 518bbbb..fe2cc6e 100644 +--- a/arch/x86/include/asm/kdebug.h ++++ b/arch/x86/include/asm/kdebug.h +@@ -26,7 +26,7 @@ extern void die(const char *, struct pt_regs *,long); + extern int __must_check __die(const char *, struct pt_regs *, long); + extern void show_registers(struct pt_regs *regs); + extern void show_trace(struct task_struct *t, struct pt_regs *regs, +- unsigned long *sp); ++ unsigned long *sp, unsigned long bp); + extern void __show_regs(struct pt_regs *regs, int all); + extern void show_regs(struct pt_regs *regs); + extern unsigned long oops_begin(void); +diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h +index 52b5c7e..d7e89c8 100644 +--- a/arch/x86/include/asm/stacktrace.h ++++ b/arch/x86/include/asm/stacktrace.h +@@ -47,7 +47,7 @@ struct stacktrace_ops { + }; + + void dump_trace(struct task_struct *tsk, struct pt_regs *regs, +- unsigned long *stack, ++ unsigned long *stack, unsigned long bp, + const struct stacktrace_ops *ops, void *data); + + #ifdef CONFIG_X86_32 +@@ -86,11 +86,11 @@ stack_frame(struct task_struct *task, struct pt_regs *regs) + + extern void + show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, +- unsigned long *stack, char *log_lvl); ++ unsigned long *stack, unsigned long bp, char *log_lvl); + + extern void + show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, +- unsigned long *sp, char *log_lvl); ++ unsigned long *sp, unsigned long bp, char *log_lvl); + + extern unsigned int code_bytes; + +diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c +index 279bc9d..3061276 100644 +--- a/arch/x86/kernel/cpu/perf_event.c ++++ b/arch/x86/kernel/cpu/perf_event.c +@@ -1792,7 +1792,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) + + perf_callchain_store(entry, regs->ip); + +- dump_trace(NULL, regs, NULL, &backtrace_ops, entry); ++ dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); + } + + #ifdef CONFIG_COMPAT +diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c +index 220a1c1..999e279 100644 +--- a/arch/x86/kernel/dumpstack.c ++++ b/arch/x86/kernel/dumpstack.c +@@ -175,21 +175,21 @@ static const struct stacktrace_ops print_trace_ops = { + + void + show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, +- unsigned long *stack, char *log_lvl) ++ unsigned long *stack, unsigned long bp, char *log_lvl) + { + printk("%sCall Trace:\n", log_lvl); +- dump_trace(task, regs, stack, &print_trace_ops, log_lvl); ++ dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); + } + + void show_trace(struct task_struct *task, struct pt_regs *regs, +- unsigned long *stack) ++ unsigned long *stack, unsigned long bp) + { +- show_trace_log_lvl(task, regs, stack, ""); ++ show_trace_log_lvl(task, regs, stack, bp, ""); + } + + void show_stack(struct task_struct *task, unsigned long *sp) + { +- show_stack_log_lvl(task, NULL, sp, ""); ++ show_stack_log_lvl(task, NULL, sp, 0, ""); + } + + /* +@@ -197,14 +197,16 @@ void show_stack(struct task_struct *task, unsigned long *sp) + */ + void dump_stack(void) + { ++ unsigned long bp; + unsigned long stack; + ++ bp = stack_frame(current, NULL); + printk("Pid: %d, comm: %.20s %s %s %.*s\n", + current->pid, current->comm, print_tainted(), + init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version); +- show_trace(NULL, NULL, &stack); ++ show_trace(NULL, NULL, &stack, bp); + } + EXPORT_SYMBOL(dump_stack); + +diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c +index 74cc1ed..3b97a80 100644 +--- a/arch/x86/kernel/dumpstack_32.c ++++ b/arch/x86/kernel/dumpstack_32.c +@@ -17,12 +17,11 @@ + #include + + +-void dump_trace(struct task_struct *task, +- struct pt_regs *regs, unsigned long *stack, ++void dump_trace(struct task_struct *task, struct pt_regs *regs, ++ unsigned long *stack, unsigned long bp, + const struct stacktrace_ops *ops, void *data) + { + int graph = 0; +- unsigned long bp; + + if (!task) + task = current; +@@ -35,7 +34,9 @@ void dump_trace(struct task_struct *task, + stack = (unsigned long *)task->thread.sp; + } + +- bp = stack_frame(task, regs); ++ if (!bp) ++ bp = stack_frame(task, regs); ++ + for (;;) { + struct thread_info *context; + +@@ -55,7 +56,7 @@ EXPORT_SYMBOL(dump_trace); + + void + show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, +- unsigned long *sp, char *log_lvl) ++ unsigned long *sp, unsigned long bp, char *log_lvl) + { + unsigned long *stack; + int i; +@@ -77,7 +78,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, + touch_nmi_watchdog(); + } + printk(KERN_CONT "\n"); +- show_trace_log_lvl(task, regs, sp, log_lvl); ++ show_trace_log_lvl(task, regs, sp, bp, log_lvl); + } + + +@@ -102,7 +103,7 @@ void show_registers(struct pt_regs *regs) + u8 *ip; + + printk(KERN_EMERG "Stack:\n"); +- show_stack_log_lvl(NULL, regs, ®s->sp, KERN_EMERG); ++ show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG); + + printk(KERN_EMERG "Code: "); + +diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c +index a6b6fcf..e71c98d 100644 +--- a/arch/x86/kernel/dumpstack_64.c ++++ b/arch/x86/kernel/dumpstack_64.c +@@ -139,8 +139,8 @@ fixup_bp_irq_link(unsigned long bp, unsigned long *stack, + * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack + */ + +-void dump_trace(struct task_struct *task, +- struct pt_regs *regs, unsigned long *stack, ++void dump_trace(struct task_struct *task, struct pt_regs *regs, ++ unsigned long *stack, unsigned long bp, + const struct stacktrace_ops *ops, void *data) + { + const unsigned cpu = get_cpu(); +@@ -150,7 +150,6 @@ void dump_trace(struct task_struct *task, + struct thread_info *tinfo; + int graph = 0; + unsigned long dummy; +- unsigned long bp; + + if (!task) + task = current; +@@ -161,7 +160,8 @@ void dump_trace(struct task_struct *task, + stack = (unsigned long *)task->thread.sp; + } + +- bp = stack_frame(task, regs); ++ if (!bp) ++ bp = stack_frame(task, regs); + /* + * Print function call entries in all stacks, starting at the + * current stack address. If the stacks consist of nested +@@ -225,7 +225,7 @@ EXPORT_SYMBOL(dump_trace); + + void + show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, +- unsigned long *sp, char *log_lvl) ++ unsigned long *sp, unsigned long bp, char *log_lvl) + { + unsigned long *irq_stack_end; + unsigned long *irq_stack; +@@ -269,7 +269,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, + preempt_enable(); + + printk(KERN_CONT "\n"); +- show_trace_log_lvl(task, regs, sp, log_lvl); ++ show_trace_log_lvl(task, regs, sp, bp, log_lvl); + } + + void show_registers(struct pt_regs *regs) +@@ -298,7 +298,7 @@ void show_registers(struct pt_regs *regs) + + printk(KERN_EMERG "Stack:\n"); + show_stack_log_lvl(NULL, regs, (unsigned long *)sp, +- KERN_EMERG); ++ 0, KERN_EMERG); + + printk(KERN_EMERG "Code: "); + +diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c +index 99fa3ad..d46cbe4 100644 +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -87,7 +87,7 @@ void exit_thread(void) + void show_regs(struct pt_regs *regs) + { + show_registers(regs); +- show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs)); ++ show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs), 0); + } + + void show_regs_common(void) +diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c +index 938c8e1..6515733 100644 +--- a/arch/x86/kernel/stacktrace.c ++++ b/arch/x86/kernel/stacktrace.c +@@ -73,7 +73,7 @@ static const struct stacktrace_ops save_stack_ops_nosched = { + */ + void save_stack_trace(struct stack_trace *trace) + { +- dump_trace(current, NULL, NULL, &save_stack_ops, trace); ++ dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; + } +@@ -81,14 +81,14 @@ EXPORT_SYMBOL_GPL(save_stack_trace); + + void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs) + { +- dump_trace(current, regs, NULL, &save_stack_ops, trace); ++ dump_trace(current, regs, NULL, 0, &save_stack_ops, trace); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; + } + + void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) + { +- dump_trace(tsk, NULL, NULL, &save_stack_ops_nosched, trace); ++ dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; + } +diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c +index 72cbec1..2d49d4e 100644 +--- a/arch/x86/oprofile/backtrace.c ++++ b/arch/x86/oprofile/backtrace.c +@@ -126,7 +126,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) + if (!user_mode_vm(regs)) { + unsigned long stack = kernel_stack_pointer(regs); + if (depth) +- dump_trace(NULL, regs, (unsigned long *)stack, ++ dump_trace(NULL, regs, (unsigned long *)stack, 0, + &backtrace_ops, &depth); + return; + } From 3bcf43a573ac2d33911487c34d2678de0b9693dc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 3 May 2011 16:57:58 -0400 Subject: [PATCH 45/99] radeon updates from 2.6.39 with cayman + fixes for lots of things including Fusion. vblank fix for core drm --- drm-radeon-update.patch | 4807 +++++++++++++++++++++++++++++ drm-vblank-events-fix-hangs.patch | 60 + kernel.spec | 13 +- 3 files changed, 4879 insertions(+), 1 deletion(-) create mode 100644 drm-radeon-update.patch create mode 100644 drm-vblank-events-fix-hangs.patch diff --git a/drm-radeon-update.patch b/drm-radeon-update.patch new file mode 100644 index 000000000..8725c021b --- /dev/null +++ b/drm-radeon-update.patch @@ -0,0 +1,4807 @@ +commit 6d7f810bacd0fc2cf3966ec5d756a23735cb781e +Author: Alex Deucher +Date: Tue May 3 19:28:02 2011 -0400 + + drm/radeon/kms: fix gart setup on fusion parts (v2) + + Out of the entire GART/VM subsystem, the hw designers changed + the location of 3 regs. + + v2: airlied: add parameter for userspace to work from. + + Signed-off-by: Alex Deucher + Signed-off-by: Jerome Glisse + Cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 00a99cbeca8ffb6d6165f388230ad49786a1a64e +Author: Dave Airlie +Date: Sun May 1 20:16:30 2011 +1000 + + drm/radeon: fix regression on atom cards with hardcoded EDID record. + + Since fafcf94e2b5732d1e13b440291c53115d2b172e9 introduced an edid size, it seems to have broken this path. + + This manifest as oops on T500 Lenovo laptops with dual graphics primarily. + + Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33812 + + cc: stable@kernel.org + Reviewed-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit ea9254cde5e773424d3af177012ab8019a9a1664 +Author: Alex Deucher +Date: Tue Apr 26 13:27:43 2011 -0400 + + drm/radeon/kms: add info query for tile pipes + + needed by mesa for htile setup. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 5ac5da9419c4b51efa17ef222b0ac82d1af63af8 +Author: Alex Deucher +Date: Tue Apr 26 13:10:20 2011 -0400 + + drm/radeon/kms: add missing safe regs for 6xx/7xx + + needed for HiS in mesa. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 7ad87e13c92ac772cc1eced43df0555ec4a71bbc +Author: Cédric Cano +Date: Tue Apr 19 11:07:13 2011 -0400 + + drm/radeon/kms: fix IH writeback on r6xx+ on big endian machines + + agd5f: fix commit message. + + Signed-off-by: Cedric Cano + Reviewed-by: Michel Dänzer + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 10045c9e73dfa9e53fb429c6d5b1a2261da0ad51 +Author: Alex Deucher +Date: Thu Apr 14 19:07:34 2011 -0400 + + drm/radeon/kms: adjust evergreen display watermark setup + + This patch fixes two issues: + - A disabled crtc does not use any lb, so return 0 for + lb size. This makes the display priority calculation + more exact. + - Only use 1/2 and whole lb partitions. Using smaller + partitions can cause underflow to one of the displays + if you have multiple large displays on the same lb. + + Fixes: + https://bugs.freedesktop.org/show_bug.cgi?id=34534 + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit ea7537dfbe693d8a0d9a3f8dc040fea8d74db625 +Author: Alex Deucher +Date: Tue Apr 12 14:49:24 2011 -0400 + + drm/radeon/kms: properly program vddci on evergreen+ + + Change vddci as well as vddc when changing power modes + on evergreen/ni. Also, properly set vddci on boot up + for ni cards. The vbios only sets the limited clocks + and voltages on boot until the mc ucode is loaded. This + should fix stability problems on some btc cards. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit d45b8c22db23566ec99d330afe69ca0eb99877e3 +Author: Alex Deucher +Date: Tue Apr 12 14:49:23 2011 -0400 + + drm/radeon/kms: add voltage type to atom set voltage function + + This is needed for setting voltages other than vddc. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit ced08b02a89170bfcb0a7cff2b89000fce712efa +Author: Alex Deucher +Date: Tue Apr 12 13:40:18 2011 -0400 + + drm/radeon/kms: fix pcie_p callbacks on btc and cayman + + btc and cayman asics use the same callback for + pcie port registers. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 7e2f10779d1b11b9dc086d95dada8f2d441fcb7c +Author: Alex Deucher +Date: Sat Apr 2 09:15:50 2011 -0400 + + drm/radeon/kms: pageflipping cleanup for avivo+ + + Avoid touching the flip setup regs while + acceleration is running. Set them at modeset + rather than during pageflip. Touching these + regs while acceleration is active caused hangs + on pre-avivo chips. These chips do not seem + to be affected, but better safe than sorry, + plus it avoids repeatedly reprogramming the + regs every flip. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit c079101fc0747d6924edf6b476793267c8707731 +Author: Alex Deucher +Date: Sat Apr 2 09:09:08 2011 -0400 + + drm/radeon/kms: Add support for tv-out dongle on G5 9600 + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 80b359eb082c7e84c9ee970a98578dd409211f52 +Author: Alex Deucher +Date: Wed Mar 2 10:21:05 2011 -0500 + + drm/radeon/kms: allow max clock of 340 Mhz on hdmi 1.3+ + + hdmi 1.3 raises the max clock from 165 Mhz to 340 Mhz. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 4b77fd7824c73fd19a06b3942f498eb23740826d +Author: Alex Deucher +Date: Wed Mar 2 20:07:40 2011 -0500 + + drm/radeon/kms: cayman/evergreen cs checker updates + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 8f62b708e5f4a3e7b617fa7e5ddd9e9becf85920 +Author: Alex Deucher +Date: Wed Mar 2 20:07:39 2011 -0500 + + drm/radeon/kms/cayman: always set certain VGT regs at CP init + + These should be handled by the clear_state setup, but set them + directly as well just to be sure. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 25bfa1ee008f6d8871dd71c529ba25f6492e6b27 +Author: Alex Deucher +Date: Wed Mar 2 20:07:38 2011 -0500 + + drm/radeon/kms: additional default context regs for cayman + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 65a9c7094637d67ffec51dc7373c53f1e4836b79 +Author: Alex Deucher +Date: Wed Mar 2 20:07:37 2011 -0500 + + drm/radeon/kms: add cayman CS check support + + Added to existing evergreen CS checker. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 4655de2aadf3ef4d885600214f8bf989e35087fb +Author: Alex Deucher +Date: Wed Mar 2 20:07:36 2011 -0500 + + drm/radeon/kms: add radeon_asic entry for cayman + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 6110f1c930fa057a0380cbf786350dbd01e9dab9 +Author: Alex Deucher +Date: Wed Mar 2 20:07:35 2011 -0500 + + drm/radeon/kms: add cayman safe regs + + For the CS checker. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit f0c8c61d41e93b1b616b5eb5d29b1bdccb50b6ec +Author: Alex Deucher +Date: Wed Mar 2 20:07:34 2011 -0500 + + drm/radeon/kms/cayman: add asic init/startup/fini/suspend/resume functions + + Cayman is different enough from evergreen to warrant it's own functions. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit f772bd94e036bf8809359b4e37c1aa2ec2dcf4f3 +Author: Alex Deucher +Date: Wed Mar 2 20:07:33 2011 -0500 + + drm/radeon/kms: add cayman asic reset support + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit f83146d1532f80351e8b08ae6063d5792e56914f +Author: Alex Deucher +Date: Wed Mar 2 20:07:32 2011 -0500 + + drm/radeon/kms: add support for cayman irqs + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 004e9f16d1a0dbf2a8787f64b70e8bb3b86abe21 +Author: Alex Deucher +Date: Wed Mar 2 20:07:31 2011 -0500 + + drm/radeon/kms: add support for CP setup on cayman asics + + Cayman asics have 3 ring buffers: + ring 0 supports both gfx and compute + rings 1 and 2 are compute only + + At the moment we only support ring 0. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 5ca642f168996cd6f1dda99ffb17855cc65e493e +Author: Alex Deucher +Date: Wed Mar 2 20:07:30 2011 -0500 + + drm/radeon/kms: add support for cayman gart setup + + This patch sets up the gart in legacy mode. We + probably want to switch to full VM mode at some point. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 8e72474ace85f7a13c88dc360cbfc28dc2fe67e5 +Author: Alex Deucher +Date: Wed Mar 2 20:07:29 2011 -0500 + + drm/radeon/kms: add gpu_init function for cayman + + This may some work to get accel going. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 5b22a85481f452a23dd625e9a389d8f5c0f9b269 +Author: Alex Deucher +Date: Wed Mar 2 20:07:28 2011 -0500 + + drm/radeon/kms: add ucode loader for cayman + + The MC ucode is no longer loaded by the vbios + tables as on previous asics. It now must be loaded + by the driver. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 11fa70b2e7022d25933fc1d17518aeb054752dc9 +Author: Alex Deucher +Date: Wed Mar 2 20:07:27 2011 -0500 + + drm/radeon/kms: add cayman chip family + + Cayman is DCE5 display plus a new 4-way shader block. + 3D state programming is similar to evergreen. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit fe4608d030a121d61dfbc7a80c57706b89fbdabd +Author: Dave Airlie +Date: Tue Mar 1 14:32:27 2011 +1000 + + drm/radeon: add new getparam for number of backends. + + This allows userspace to work out how many DBs there are + for conditional rendering to work. + + Signed-off-by: Dave Airlie + +commit cd3e8f6393bce904aad911b8c261e14d5201d347 +Author: Dave Airlie +Date: Tue Mar 1 12:10:43 2011 +1000 + + drm/radeon: bump version to 2.9 + + This lets r600g enable texture formats and some more extensions. + + Signed-off-by: Dave Airlie + +commit 7855f7a2d8095e04916a097d14cad09c85ebf08a +Author: Dave Airlie +Date: Mon Feb 28 16:11:48 2011 +1000 + + drm/r600: parse the set predication command. (v2) + + This is required for NV_conditional_render and EXT_transform_feedback. + + v2: add evergreen support. + + Signed-off-by: Dave Airlie + +commit 85d824cf58fec0921e4e559cd91dbea50cb7bc20 +Author: Dave Airlie +Date: Mon Feb 28 14:27:03 2011 +1000 + + drm/radeon: make sure ib reads are in-order. + + have to read values from the IB in order as we could cross + a page boundary at any time and won't be able to go backwards. + + Signed-off-by: Dave Airlie + +commit a3f1872b53f046631f48faf19e932f6c9b020446 +Author: Dan Carpenter +Date: Sat Feb 26 04:48:18 2011 +0300 + + drm/radeon/r600_cs: off by one errors + + There are a bunch of off by one errors in the sanity checks here. + + Signed-off-by: Dan Carpenter + Signed-off-by: Dave Airlie + +commit 6c23a39f630acd5c792b731372f5fa227009c7ee +Author: Dave Airlie +Date: Fri Feb 18 05:51:58 2011 +0000 + + drm/radeon: overhaul texture checking. (v3) + + the texture checking code didn't work for block formats like s3tc, + this overhauls it to work for all types. + + v2: add texture array support. + v3: add subsampled formats + + Signed-off-by: Dave Airlie +diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile +index e47eecf..3896ef8 100644 +--- a/drivers/gpu/drm/radeon/Makefile ++++ b/drivers/gpu/drm/radeon/Makefile +@@ -36,6 +36,9 @@ $(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable + $(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable + $(call if_changed,mkregtable) + ++$(obj)/cayman_reg_safe.h: $(src)/reg_srcs/cayman $(obj)/mkregtable ++ $(call if_changed,mkregtable) ++ + $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h + + $(obj)/r200.o: $(obj)/r200_reg_safe.h +@@ -50,7 +53,7 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h + + $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h + +-$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h ++$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h $(obj)/cayman_reg_safe.h + + radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \ + radeon_irq.o r300_cmdbuf.o r600_cp.o +@@ -66,7 +69,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ + r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ + r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ + evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ +- radeon_trace_points.o ni.o ++ radeon_trace_points.o ni.o cayman_blit_shaders.o + + radeon-$(CONFIG_COMPAT) += radeon_ioc32.o + radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index bede31c..2bab32f 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -1011,6 +1011,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + uint64_t fb_location; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); ++ u32 tmp; + int r; + + /* no fb bound */ +@@ -1139,6 +1140,15 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, + (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); + ++ /* pageflip setup */ ++ /* make sure flip is at vb rather than hb */ ++ tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); ++ tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; ++ WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); ++ ++ /* set pageflip to happen anywhere in vblank interval */ ++ WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); ++ + if (!atomic && fb && fb != crtc->fb) { + radeon_fb = to_radeon_framebuffer(fb); + rbo = radeon_fb->obj->driver_private; +@@ -1169,6 +1179,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, + uint64_t fb_location; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; ++ u32 tmp; + int r; + + /* no fb bound */ +@@ -1296,6 +1307,15 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, + WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, + (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); + ++ /* pageflip setup */ ++ /* make sure flip is at vb rather than hb */ ++ tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); ++ tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; ++ WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); ++ ++ /* set pageflip to happen anywhere in vblank interval */ ++ WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); ++ + if (!atomic && fb && fb != crtc->fb) { + radeon_fb = to_radeon_framebuffer(fb); + rbo = radeon_fb->obj->driver_private; +diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c +new file mode 100644 +index 0000000..e148ab0 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c +@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2010 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: ++ * Alex Deucher ++ */ ++ ++#include ++#include ++ ++/* ++ * evergreen cards need to use the 3D engine to blit data which requires ++ * quite a bit of hw state setup. Rather than pull the whole 3D driver ++ * (which normally generates the 3D state) into the DRM, we opt to use ++ * statically generated state tables. The regsiter state and shaders ++ * were hand generated to support blitting functionality. See the 3D ++ * driver or documentation for descriptions of the registers and ++ * shader instructions. ++ */ ++ ++const u32 cayman_default_state[] = ++{ ++ /* XXX fill in additional blit state */ ++ ++ 0xc0026900, ++ 0x00000316, ++ 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ ++ 0x00000010, /* */ ++ ++ 0xc0026900, ++ 0x000000d9, ++ 0x00000000, /* CP_RINGID */ ++ 0x00000000, /* CP_VMID */ ++}; ++ ++const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state); +diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.h b/drivers/gpu/drm/radeon/cayman_blit_shaders.h +new file mode 100644 +index 0000000..33b75e5 +--- /dev/null ++++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright 2010 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ */ ++ ++#ifndef CAYMAN_BLIT_SHADERS_H ++#define CAYMAN_BLIT_SHADERS_H ++ ++extern const u32 cayman_default_state[]; ++ ++extern const u32 cayman_default_size; ++ ++#endif +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 6140ea1..f7e0376 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -43,17 +43,6 @@ static void evergreen_pcie_gen2_enable(struct radeon_device *rdev); + + void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) + { +- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; +- u32 tmp; +- +- /* make sure flip is at vb rather than hb */ +- tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); +- tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; +- WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); +- +- /* set pageflip to happen anywhere in vblank interval */ +- WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); +- + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); + } +@@ -131,11 +120,16 @@ void evergreen_pm_misc(struct radeon_device *rdev) + struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + +- if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { +- if (voltage->voltage != rdev->pm.current_vddc) { +- radeon_atom_set_voltage(rdev, voltage->voltage); ++ if (voltage->type == VOLTAGE_SW) { ++ if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { ++ radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; +- DRM_DEBUG("Setting: v: %d\n", voltage->voltage); ++ DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); ++ } ++ if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { ++ radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); ++ rdev->pm.current_vddci = voltage->vddci; ++ DRM_DEBUG("Setting: vddci: %d\n", voltage->vddci); + } + } + } +@@ -359,7 +353,7 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, + struct drm_display_mode *mode, + struct drm_display_mode *other_mode) + { +- u32 tmp = 0; ++ u32 tmp; + /* + * Line Buffer Setup + * There are 3 line buffers, each one shared by 2 display controllers. +@@ -369,64 +363,63 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, + * first display controller + * 0 - first half of lb (3840 * 2) + * 1 - first 3/4 of lb (5760 * 2) +- * 2 - whole lb (7680 * 2) ++ * 2 - whole lb (7680 * 2), other crtc must be disabled + * 3 - first 1/4 of lb (1920 * 2) + * second display controller + * 4 - second half of lb (3840 * 2) + * 5 - second 3/4 of lb (5760 * 2) +- * 6 - whole lb (7680 * 2) ++ * 6 - whole lb (7680 * 2), other crtc must be disabled + * 7 - last 1/4 of lb (1920 * 2) + */ +- if (mode && other_mode) { +- if (mode->hdisplay > other_mode->hdisplay) { +- if (mode->hdisplay > 2560) +- tmp = 1; /* 3/4 */ +- else +- tmp = 0; /* 1/2 */ +- } else if (other_mode->hdisplay > mode->hdisplay) { +- if (other_mode->hdisplay > 2560) +- tmp = 3; /* 1/4 */ +- else +- tmp = 0; /* 1/2 */ +- } else ++ /* this can get tricky if we have two large displays on a paired group ++ * of crtcs. Ideally for multiple large displays we'd assign them to ++ * non-linked crtcs for maximum line buffer allocation. ++ */ ++ if (radeon_crtc->base.enabled && mode) { ++ if (other_mode) + tmp = 0; /* 1/2 */ +- } else if (mode) +- tmp = 2; /* whole */ +- else if (other_mode) +- tmp = 3; /* 1/4 */ ++ else ++ tmp = 2; /* whole */ ++ } else ++ tmp = 0; + + /* second controller of the pair uses second half of the lb */ + if (radeon_crtc->crtc_id % 2) + tmp += 4; + WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp); + +- switch (tmp) { +- case 0: +- case 4: +- default: +- if (ASIC_IS_DCE5(rdev)) +- return 4096 * 2; +- else +- return 3840 * 2; +- case 1: +- case 5: +- if (ASIC_IS_DCE5(rdev)) +- return 6144 * 2; +- else +- return 5760 * 2; +- case 2: +- case 6: +- if (ASIC_IS_DCE5(rdev)) +- return 8192 * 2; +- else +- return 7680 * 2; +- case 3: +- case 7: +- if (ASIC_IS_DCE5(rdev)) +- return 2048 * 2; +- else +- return 1920 * 2; ++ if (radeon_crtc->base.enabled && mode) { ++ switch (tmp) { ++ case 0: ++ case 4: ++ default: ++ if (ASIC_IS_DCE5(rdev)) ++ return 4096 * 2; ++ else ++ return 3840 * 2; ++ case 1: ++ case 5: ++ if (ASIC_IS_DCE5(rdev)) ++ return 6144 * 2; ++ else ++ return 5760 * 2; ++ case 2: ++ case 6: ++ if (ASIC_IS_DCE5(rdev)) ++ return 8192 * 2; ++ else ++ return 7680 * 2; ++ case 3: ++ case 7: ++ if (ASIC_IS_DCE5(rdev)) ++ return 2048 * 2; ++ else ++ return 1920 * 2; ++ } + } ++ ++ /* controller not enabled, so no lb used */ ++ return 0; + } + + static u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev) +@@ -804,7 +797,7 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) + } + } + +-static int evergreen_mc_wait_for_idle(struct radeon_device *rdev) ++int evergreen_mc_wait_for_idle(struct radeon_device *rdev) + { + unsigned i; + u32 tmp; +@@ -869,9 +862,15 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); +- WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); +- WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); +- WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); ++ if (rdev->flags & RADEON_IS_IGP) { ++ WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp); ++ WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp); ++ WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp); ++ } else { ++ WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); ++ WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); ++ WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); ++ } + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); +@@ -957,7 +956,7 @@ void evergreen_agp_enable(struct radeon_device *rdev) + WREG32(VM_CONTEXT1_CNTL, 0); + } + +-static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) ++void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) + { + save->vga_control[0] = RREG32(D1VGA_CONTROL); + save->vga_control[1] = RREG32(D2VGA_CONTROL); +@@ -1011,7 +1010,7 @@ static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_sa + WREG32(EVERGREEN_D6VGA_CONTROL, 0); + } + +-static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) ++void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) + { + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); +@@ -1108,7 +1107,7 @@ static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_ + WREG32(VGA_RENDER_CONTROL, save->vga_render_control); + } + +-static void evergreen_mc_program(struct radeon_device *rdev) ++void evergreen_mc_program(struct radeon_device *rdev) + { + struct evergreen_mc_save save; + u32 tmp; +@@ -2576,7 +2575,7 @@ void evergreen_irq_disable(struct radeon_device *rdev) + evergreen_disable_interrupt_state(rdev); + } + +-static void evergreen_irq_suspend(struct radeon_device *rdev) ++void evergreen_irq_suspend(struct radeon_device *rdev) + { + evergreen_irq_disable(rdev); + r600_rlc_stop(rdev); +@@ -2587,7 +2586,7 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) + u32 wptr, tmp; + + if (rdev->wb.enabled) +- wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]; ++ wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); + else + wptr = RREG32(IH_RB_WPTR); + +@@ -2899,7 +2898,7 @@ static int evergreen_startup(struct radeon_device *rdev) + return r; + } + } +- r = btc_mc_load_microcode(rdev); ++ r = ni_mc_load_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); + return r; +@@ -2930,11 +2929,6 @@ static int evergreen_startup(struct radeon_device *rdev) + rdev->asic->copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } +- /* XXX: ontario has problems blitting to gart at the moment */ +- if (rdev->family == CHIP_PALM) { +- rdev->asic->copy = NULL; +- radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); +- } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); +@@ -2981,7 +2975,7 @@ int evergreen_resume(struct radeon_device *rdev) + + r = evergreen_startup(rdev); + if (r) { +- DRM_ERROR("r600 startup failed on resume\n"); ++ DRM_ERROR("evergreen startup failed on resume\n"); + return r; + } + +@@ -3061,7 +3055,7 @@ int evergreen_init(struct radeon_device *rdev) + } + /* Must be an ATOMBIOS */ + if (!rdev->is_atom_bios) { +- dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); ++ dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n"); + return -EINVAL; + } + r = radeon_atombios_init(rdev); +diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c +index 345a75a..5e4f9f8 100644 +--- a/drivers/gpu/drm/radeon/evergreen_cs.c ++++ b/drivers/gpu/drm/radeon/evergreen_cs.c +@@ -29,6 +29,7 @@ + #include "radeon.h" + #include "evergreend.h" + #include "evergreen_reg_safe.h" ++#include "cayman_reg_safe.h" + + static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, + struct radeon_cs_reloc **cs_reloc); +@@ -425,18 +426,28 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 + { + struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; + struct radeon_cs_reloc *reloc; +- u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); ++ u32 last_reg; + u32 m, i, tmp, *ib; + int r; + ++ if (p->rdev->family >= CHIP_CAYMAN) ++ last_reg = ARRAY_SIZE(cayman_reg_safe_bm); ++ else ++ last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); ++ + i = (reg >> 7); + if (i > last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return -EINVAL; + } + m = 1 << ((reg >> 2) & 31); +- if (!(evergreen_reg_safe_bm[i] & m)) +- return 0; ++ if (p->rdev->family >= CHIP_CAYMAN) { ++ if (!(cayman_reg_safe_bm[i] & m)) ++ return 0; ++ } else { ++ if (!(evergreen_reg_safe_bm[i] & m)) ++ return 0; ++ } + ib = p->ib->ptr; + switch (reg) { + /* force following reg to 0 in an attemp to disable out buffer +@@ -468,12 +479,42 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 + case SQ_VSTMP_RING_ITEMSIZE: + case VGT_TF_RING_SIZE: + /* get value to populate the IB don't remove */ +- tmp =radeon_get_ib_value(p, idx); +- ib[idx] = 0; ++ /*tmp =radeon_get_ib_value(p, idx); ++ ib[idx] = 0;*/ ++ break; ++ case SQ_ESGS_RING_BASE: ++ case SQ_GSVS_RING_BASE: ++ case SQ_ESTMP_RING_BASE: ++ case SQ_GSTMP_RING_BASE: ++ case SQ_HSTMP_RING_BASE: ++ case SQ_LSTMP_RING_BASE: ++ case SQ_PSTMP_RING_BASE: ++ case SQ_VSTMP_RING_BASE: ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; + case DB_DEPTH_CONTROL: + track->db_depth_control = radeon_get_ib_value(p, idx); + break; ++ case CAYMAN_DB_EQAA: ++ if (p->rdev->family < CHIP_CAYMAN) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ break; ++ case CAYMAN_DB_DEPTH_INFO: ++ if (p->rdev->family < CHIP_CAYMAN) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ break; + case DB_Z_INFO: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { +@@ -559,9 +600,23 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 + track->cb_shader_mask = radeon_get_ib_value(p, idx); + break; + case PA_SC_AA_CONFIG: ++ if (p->rdev->family >= CHIP_CAYMAN) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } + tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; + track->nsamples = 1 << tmp; + break; ++ case CAYMAN_PA_SC_AA_CONFIG: ++ if (p->rdev->family < CHIP_CAYMAN) { ++ dev_warn(p->dev, "bad SET_CONTEXT_REG " ++ "0x%04X\n", reg); ++ return -EINVAL; ++ } ++ tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK; ++ track->nsamples = 1 << tmp; ++ break; + case CB_COLOR0_VIEW: + case CB_COLOR1_VIEW: + case CB_COLOR2_VIEW: +@@ -942,6 +997,37 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + idx_value = radeon_get_ib_value(p, idx); + + switch (pkt->opcode) { ++ case PACKET3_SET_PREDICATION: ++ { ++ int pred_op; ++ int tmp; ++ if (pkt->count != 1) { ++ DRM_ERROR("bad SET PREDICATION\n"); ++ return -EINVAL; ++ } ++ ++ tmp = radeon_get_ib_value(p, idx + 1); ++ pred_op = (tmp >> 16) & 0x7; ++ ++ /* for the clear predicate operation */ ++ if (pred_op == 0) ++ return 0; ++ ++ if (pred_op > 2) { ++ DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); ++ return -EINVAL; ++ } ++ ++ r = evergreen_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad SET PREDICATION\n"); ++ return -EINVAL; ++ } ++ ++ ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); ++ ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); ++ } ++ break; + case PACKET3_CONTEXT_CONTROL: + if (pkt->count != 1) { + DRM_ERROR("bad CONTEXT_CONTROL\n"); +@@ -956,6 +1042,16 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, + return -EINVAL; + } + break; ++ case CAYMAN_PACKET3_DEALLOC_STATE: ++ if (p->rdev->family < CHIP_CAYMAN) { ++ DRM_ERROR("bad PACKET3_DEALLOC_STATE\n"); ++ return -EINVAL; ++ } ++ if (pkt->count) { ++ DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); ++ return -EINVAL; ++ } ++ break; + case PACKET3_INDEX_BASE: + if (pkt->count != 1) { + DRM_ERROR("bad INDEX_BASE\n"); +diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h +index eb4acf4..9453384 100644 +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -221,6 +221,11 @@ + #define MC_VM_MD_L1_TLB0_CNTL 0x2654 + #define MC_VM_MD_L1_TLB1_CNTL 0x2658 + #define MC_VM_MD_L1_TLB2_CNTL 0x265C ++ ++#define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C ++#define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 ++#define FUS_MC_VM_MD_L1_TLB2_CNTL 0x2664 ++ + #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C + #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 + #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 +@@ -755,13 +760,21 @@ + + #define SQ_CONST_MEM_BASE 0x8df8 + ++#define SQ_ESGS_RING_BASE 0x8c40 + #define SQ_ESGS_RING_SIZE 0x8c44 ++#define SQ_GSVS_RING_BASE 0x8c48 + #define SQ_GSVS_RING_SIZE 0x8c4c ++#define SQ_ESTMP_RING_BASE 0x8c50 + #define SQ_ESTMP_RING_SIZE 0x8c54 ++#define SQ_GSTMP_RING_BASE 0x8c58 + #define SQ_GSTMP_RING_SIZE 0x8c5c ++#define SQ_VSTMP_RING_BASE 0x8c60 + #define SQ_VSTMP_RING_SIZE 0x8c64 ++#define SQ_PSTMP_RING_BASE 0x8c68 + #define SQ_PSTMP_RING_SIZE 0x8c6c ++#define SQ_LSTMP_RING_BASE 0x8e10 + #define SQ_LSTMP_RING_SIZE 0x8e14 ++#define SQ_HSTMP_RING_BASE 0x8e18 + #define SQ_HSTMP_RING_SIZE 0x8e1c + #define VGT_TF_RING_SIZE 0x8988 + +@@ -1093,5 +1106,14 @@ + #define SQ_TEX_RESOURCE_WORD6_0 0x30018 + #define SQ_TEX_RESOURCE_WORD7_0 0x3001c + ++/* cayman 3D regs */ ++#define CAYMAN_VGT_OFFCHIP_LDS_BASE 0x89B0 ++#define CAYMAN_DB_EQAA 0x28804 ++#define CAYMAN_DB_DEPTH_INFO 0x2803C ++#define CAYMAN_PA_SC_AA_CONFIG 0x28BE0 ++#define CAYMAN_MSAA_NUM_SAMPLES_SHIFT 0 ++#define CAYMAN_MSAA_NUM_SAMPLES_MASK 0x7 ++/* cayman packet3 addition */ ++#define CAYMAN_PACKET3_DEALLOC_STATE 0x14 + + #endif +diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +index 5e0bef8..8c199c4 100644 +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -31,12 +31,25 @@ + #include "nid.h" + #include "atom.h" + #include "ni_reg.h" ++#include "cayman_blit_shaders.h" ++ ++extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); ++extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); ++extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); ++extern void evergreen_mc_program(struct radeon_device *rdev); ++extern void evergreen_irq_suspend(struct radeon_device *rdev); ++extern int evergreen_mc_init(struct radeon_device *rdev); + + #define EVERGREEN_PFP_UCODE_SIZE 1120 + #define EVERGREEN_PM4_UCODE_SIZE 1376 + #define EVERGREEN_RLC_UCODE_SIZE 768 + #define BTC_MC_UCODE_SIZE 6024 + ++#define CAYMAN_PFP_UCODE_SIZE 2176 ++#define CAYMAN_PM4_UCODE_SIZE 2176 ++#define CAYMAN_RLC_UCODE_SIZE 1024 ++#define CAYMAN_MC_UCODE_SIZE 6037 ++ + /* Firmware Names */ + MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); + MODULE_FIRMWARE("radeon/BARTS_me.bin"); +@@ -48,6 +61,10 @@ MODULE_FIRMWARE("radeon/TURKS_mc.bin"); + MODULE_FIRMWARE("radeon/CAICOS_pfp.bin"); + MODULE_FIRMWARE("radeon/CAICOS_me.bin"); + MODULE_FIRMWARE("radeon/CAICOS_mc.bin"); ++MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin"); ++MODULE_FIRMWARE("radeon/CAYMAN_me.bin"); ++MODULE_FIRMWARE("radeon/CAYMAN_mc.bin"); ++MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin"); + + #define BTC_IO_MC_REGS_SIZE 29 + +@@ -147,12 +164,44 @@ static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { + {0x0000009f, 0x00916a00} + }; + +-int btc_mc_load_microcode(struct radeon_device *rdev) ++static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { ++ {0x00000077, 0xff010100}, ++ {0x00000078, 0x00000000}, ++ {0x00000079, 0x00001434}, ++ {0x0000007a, 0xcc08ec08}, ++ {0x0000007b, 0x00040000}, ++ {0x0000007c, 0x000080c0}, ++ {0x0000007d, 0x09000000}, ++ {0x0000007e, 0x00210404}, ++ {0x00000081, 0x08a8e800}, ++ {0x00000082, 0x00030444}, ++ {0x00000083, 0x00000000}, ++ {0x00000085, 0x00000001}, ++ {0x00000086, 0x00000002}, ++ {0x00000087, 0x48490000}, ++ {0x00000088, 0x20244647}, ++ {0x00000089, 0x00000005}, ++ {0x0000008b, 0x66030000}, ++ {0x0000008c, 0x00006603}, ++ {0x0000008d, 0x00000100}, ++ {0x0000008f, 0x00001c0a}, ++ {0x00000090, 0xff000001}, ++ {0x00000094, 0x00101101}, ++ {0x00000095, 0x00000fff}, ++ {0x00000096, 0x00116fff}, ++ {0x00000097, 0x60010000}, ++ {0x00000098, 0x10010000}, ++ {0x00000099, 0x00006000}, ++ {0x0000009a, 0x00001000}, ++ {0x0000009f, 0x00976b00} ++}; ++ ++int ni_mc_load_microcode(struct radeon_device *rdev) + { + const __be32 *fw_data; + u32 mem_type, running, blackout = 0; + u32 *io_mc_regs; +- int i; ++ int i, ucode_size, regs_size; + + if (!rdev->mc_fw) + return -EINVAL; +@@ -160,13 +209,24 @@ int btc_mc_load_microcode(struct radeon_device *rdev) + switch (rdev->family) { + case CHIP_BARTS: + io_mc_regs = (u32 *)&barts_io_mc_regs; ++ ucode_size = BTC_MC_UCODE_SIZE; ++ regs_size = BTC_IO_MC_REGS_SIZE; + break; + case CHIP_TURKS: + io_mc_regs = (u32 *)&turks_io_mc_regs; ++ ucode_size = BTC_MC_UCODE_SIZE; ++ regs_size = BTC_IO_MC_REGS_SIZE; + break; + case CHIP_CAICOS: + default: + io_mc_regs = (u32 *)&caicos_io_mc_regs; ++ ucode_size = BTC_MC_UCODE_SIZE; ++ regs_size = BTC_IO_MC_REGS_SIZE; ++ break; ++ case CHIP_CAYMAN: ++ io_mc_regs = (u32 *)&cayman_io_mc_regs; ++ ucode_size = CAYMAN_MC_UCODE_SIZE; ++ regs_size = BTC_IO_MC_REGS_SIZE; + break; + } + +@@ -184,13 +244,13 @@ int btc_mc_load_microcode(struct radeon_device *rdev) + WREG32(MC_SEQ_SUP_CNTL, 0x00000010); + + /* load mc io regs */ +- for (i = 0; i < BTC_IO_MC_REGS_SIZE; i++) { ++ for (i = 0; i < regs_size; i++) { + WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); + WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); + } + /* load the MC ucode */ + fw_data = (const __be32 *)rdev->mc_fw->data; +- for (i = 0; i < BTC_MC_UCODE_SIZE; i++) ++ for (i = 0; i < ucode_size; i++) + WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); + + /* put the engine back into the active state */ +@@ -231,23 +291,38 @@ int ni_init_microcode(struct radeon_device *rdev) + case CHIP_BARTS: + chip_name = "BARTS"; + rlc_chip_name = "BTC"; ++ pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; ++ me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; ++ rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; ++ mc_req_size = BTC_MC_UCODE_SIZE * 4; + break; + case CHIP_TURKS: + chip_name = "TURKS"; + rlc_chip_name = "BTC"; ++ pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; ++ me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; ++ rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; ++ mc_req_size = BTC_MC_UCODE_SIZE * 4; + break; + case CHIP_CAICOS: + chip_name = "CAICOS"; + rlc_chip_name = "BTC"; ++ pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; ++ me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; ++ rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; ++ mc_req_size = BTC_MC_UCODE_SIZE * 4; ++ break; ++ case CHIP_CAYMAN: ++ chip_name = "CAYMAN"; ++ rlc_chip_name = "CAYMAN"; ++ pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; ++ me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; ++ rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4; ++ mc_req_size = CAYMAN_MC_UCODE_SIZE * 4; + break; + default: BUG(); + } + +- pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; +- me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; +- rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; +- mc_req_size = BTC_MC_UCODE_SIZE * 4; +- + DRM_INFO("Loading %s Microcode\n", chip_name); + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); +@@ -314,3 +389,1204 @@ out: + return err; + } + ++/* ++ * Core functions ++ */ ++static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, ++ u32 num_tile_pipes, ++ u32 num_backends_per_asic, ++ u32 *backend_disable_mask_per_asic, ++ u32 num_shader_engines) ++{ ++ u32 backend_map = 0; ++ u32 enabled_backends_mask = 0; ++ u32 enabled_backends_count = 0; ++ u32 num_backends_per_se; ++ u32 cur_pipe; ++ u32 swizzle_pipe[CAYMAN_MAX_PIPES]; ++ u32 cur_backend = 0; ++ u32 i; ++ bool force_no_swizzle; ++ ++ /* force legal values */ ++ if (num_tile_pipes < 1) ++ num_tile_pipes = 1; ++ if (num_tile_pipes > rdev->config.cayman.max_tile_pipes) ++ num_tile_pipes = rdev->config.cayman.max_tile_pipes; ++ if (num_shader_engines < 1) ++ num_shader_engines = 1; ++ if (num_shader_engines > rdev->config.cayman.max_shader_engines) ++ num_shader_engines = rdev->config.cayman.max_shader_engines; ++ if (num_backends_per_asic > num_shader_engines) ++ num_backends_per_asic = num_shader_engines; ++ if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) ++ num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; ++ ++ /* make sure we have the same number of backends per se */ ++ num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); ++ /* set up the number of backends per se */ ++ num_backends_per_se = num_backends_per_asic / num_shader_engines; ++ if (num_backends_per_se > rdev->config.cayman.max_backends_per_se) { ++ num_backends_per_se = rdev->config.cayman.max_backends_per_se; ++ num_backends_per_asic = num_backends_per_se * num_shader_engines; ++ } ++ ++ /* create enable mask and count for enabled backends */ ++ for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { ++ if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { ++ enabled_backends_mask |= (1 << i); ++ ++enabled_backends_count; ++ } ++ if (enabled_backends_count == num_backends_per_asic) ++ break; ++ } ++ ++ /* force the backends mask to match the current number of backends */ ++ if (enabled_backends_count != num_backends_per_asic) { ++ u32 this_backend_enabled; ++ u32 shader_engine; ++ u32 backend_per_se; ++ ++ enabled_backends_mask = 0; ++ enabled_backends_count = 0; ++ *backend_disable_mask_per_asic = CAYMAN_MAX_BACKENDS_MASK; ++ for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { ++ /* calc the current se */ ++ shader_engine = i / rdev->config.cayman.max_backends_per_se; ++ /* calc the backend per se */ ++ backend_per_se = i % rdev->config.cayman.max_backends_per_se; ++ /* default to not enabled */ ++ this_backend_enabled = 0; ++ if ((shader_engine < num_shader_engines) && ++ (backend_per_se < num_backends_per_se)) ++ this_backend_enabled = 1; ++ if (this_backend_enabled) { ++ enabled_backends_mask |= (1 << i); ++ *backend_disable_mask_per_asic &= ~(1 << i); ++ ++enabled_backends_count; ++ } ++ } ++ } ++ ++ ++ memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES); ++ switch (rdev->family) { ++ case CHIP_CAYMAN: ++ force_no_swizzle = true; ++ break; ++ default: ++ force_no_swizzle = false; ++ break; ++ } ++ if (force_no_swizzle) { ++ bool last_backend_enabled = false; ++ ++ force_no_swizzle = false; ++ for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { ++ if (((enabled_backends_mask >> i) & 1) == 1) { ++ if (last_backend_enabled) ++ force_no_swizzle = true; ++ last_backend_enabled = true; ++ } else ++ last_backend_enabled = false; ++ } ++ } ++ ++ switch (num_tile_pipes) { ++ case 1: ++ case 3: ++ case 5: ++ case 7: ++ DRM_ERROR("odd number of pipes!\n"); ++ break; ++ case 2: ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ break; ++ case 4: ++ if (force_no_swizzle) { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ swizzle_pipe[2] = 2; ++ swizzle_pipe[3] = 3; ++ } else { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 2; ++ swizzle_pipe[2] = 1; ++ swizzle_pipe[3] = 3; ++ } ++ break; ++ case 6: ++ if (force_no_swizzle) { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ swizzle_pipe[2] = 2; ++ swizzle_pipe[3] = 3; ++ swizzle_pipe[4] = 4; ++ swizzle_pipe[5] = 5; ++ } else { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 2; ++ swizzle_pipe[2] = 4; ++ swizzle_pipe[3] = 1; ++ swizzle_pipe[4] = 3; ++ swizzle_pipe[5] = 5; ++ } ++ break; ++ case 8: ++ if (force_no_swizzle) { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 1; ++ swizzle_pipe[2] = 2; ++ swizzle_pipe[3] = 3; ++ swizzle_pipe[4] = 4; ++ swizzle_pipe[5] = 5; ++ swizzle_pipe[6] = 6; ++ swizzle_pipe[7] = 7; ++ } else { ++ swizzle_pipe[0] = 0; ++ swizzle_pipe[1] = 2; ++ swizzle_pipe[2] = 4; ++ swizzle_pipe[3] = 6; ++ swizzle_pipe[4] = 1; ++ swizzle_pipe[5] = 3; ++ swizzle_pipe[6] = 5; ++ swizzle_pipe[7] = 7; ++ } ++ break; ++ } ++ ++ for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { ++ while (((1 << cur_backend) & enabled_backends_mask) == 0) ++ cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; ++ ++ backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); ++ ++ cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; ++ } ++ ++ return backend_map; ++} ++ ++static void cayman_program_channel_remap(struct radeon_device *rdev) ++{ ++ u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp; ++ ++ tmp = RREG32(MC_SHARED_CHMAP); ++ switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { ++ case 0: ++ case 1: ++ case 2: ++ case 3: ++ default: ++ /* default mapping */ ++ mc_shared_chremap = 0x00fac688; ++ break; ++ } ++ ++ switch (rdev->family) { ++ case CHIP_CAYMAN: ++ default: ++ //tcp_chan_steer_lo = 0x54763210 ++ tcp_chan_steer_lo = 0x76543210; ++ tcp_chan_steer_hi = 0x0000ba98; ++ break; ++ } ++ ++ WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo); ++ WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi); ++ WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); ++} ++ ++static u32 cayman_get_disable_mask_per_asic(struct radeon_device *rdev, ++ u32 disable_mask_per_se, ++ u32 max_disable_mask_per_se, ++ u32 num_shader_engines) ++{ ++ u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); ++ u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; ++ ++ if (num_shader_engines == 1) ++ return disable_mask_per_asic; ++ else if (num_shader_engines == 2) ++ return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); ++ else ++ return 0xffffffff; ++} ++ ++static void cayman_gpu_init(struct radeon_device *rdev) ++{ ++ u32 cc_rb_backend_disable = 0; ++ u32 cc_gc_shader_pipe_config; ++ u32 gb_addr_config = 0; ++ u32 mc_shared_chmap, mc_arb_ramcfg; ++ u32 gb_backend_map; ++ u32 cgts_tcc_disable; ++ u32 sx_debug_1; ++ u32 smx_dc_ctl0; ++ u32 gc_user_shader_pipe_config; ++ u32 gc_user_rb_backend_disable; ++ u32 cgts_user_tcc_disable; ++ u32 cgts_sm_ctrl_reg; ++ u32 hdp_host_path_cntl; ++ u32 tmp; ++ int i, j; ++ ++ switch (rdev->family) { ++ case CHIP_CAYMAN: ++ default: ++ rdev->config.cayman.max_shader_engines = 2; ++ rdev->config.cayman.max_pipes_per_simd = 4; ++ rdev->config.cayman.max_tile_pipes = 8; ++ rdev->config.cayman.max_simds_per_se = 12; ++ rdev->config.cayman.max_backends_per_se = 4; ++ rdev->config.cayman.max_texture_channel_caches = 8; ++ rdev->config.cayman.max_gprs = 256; ++ rdev->config.cayman.max_threads = 256; ++ rdev->config.cayman.max_gs_threads = 32; ++ rdev->config.cayman.max_stack_entries = 512; ++ rdev->config.cayman.sx_num_of_sets = 8; ++ rdev->config.cayman.sx_max_export_size = 256; ++ rdev->config.cayman.sx_max_export_pos_size = 64; ++ rdev->config.cayman.sx_max_export_smx_size = 192; ++ rdev->config.cayman.max_hw_contexts = 8; ++ rdev->config.cayman.sq_num_cf_insts = 2; ++ ++ rdev->config.cayman.sc_prim_fifo_size = 0x100; ++ rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; ++ rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; ++ break; ++ } ++ ++ /* Initialize HDP */ ++ for (i = 0, j = 0; i < 32; i++, j += 0x18) { ++ WREG32((0x2c14 + j), 0x00000000); ++ WREG32((0x2c18 + j), 0x00000000); ++ WREG32((0x2c1c + j), 0x00000000); ++ WREG32((0x2c20 + j), 0x00000000); ++ WREG32((0x2c24 + j), 0x00000000); ++ } ++ ++ WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); ++ ++ mc_shared_chmap = RREG32(MC_SHARED_CHMAP); ++ mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); ++ ++ cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); ++ cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); ++ cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE); ++ gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); ++ gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); ++ cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); ++ ++ rdev->config.cayman.num_shader_engines = rdev->config.cayman.max_shader_engines; ++ tmp = ((~gc_user_shader_pipe_config) & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; ++ rdev->config.cayman.num_shader_pipes_per_simd = r600_count_pipe_bits(tmp); ++ rdev->config.cayman.num_tile_pipes = rdev->config.cayman.max_tile_pipes; ++ tmp = ((~gc_user_shader_pipe_config) & INACTIVE_SIMDS_MASK) >> INACTIVE_SIMDS_SHIFT; ++ rdev->config.cayman.num_simds_per_se = r600_count_pipe_bits(tmp); ++ tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; ++ rdev->config.cayman.num_backends_per_se = r600_count_pipe_bits(tmp); ++ tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; ++ rdev->config.cayman.backend_disable_mask_per_asic = ++ cayman_get_disable_mask_per_asic(rdev, tmp, CAYMAN_MAX_BACKENDS_PER_SE_MASK, ++ rdev->config.cayman.num_shader_engines); ++ rdev->config.cayman.backend_map = ++ cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, ++ rdev->config.cayman.num_backends_per_se * ++ rdev->config.cayman.num_shader_engines, ++ &rdev->config.cayman.backend_disable_mask_per_asic, ++ rdev->config.cayman.num_shader_engines); ++ tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; ++ rdev->config.cayman.num_texture_channel_caches = r600_count_pipe_bits(tmp); ++ tmp = (mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT; ++ rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; ++ if (rdev->config.cayman.mem_max_burst_length_bytes > 512) ++ rdev->config.cayman.mem_max_burst_length_bytes = 512; ++ tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; ++ rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; ++ if (rdev->config.cayman.mem_row_size_in_kb > 4) ++ rdev->config.cayman.mem_row_size_in_kb = 4; ++ /* XXX use MC settings? */ ++ rdev->config.cayman.shader_engine_tile_size = 32; ++ rdev->config.cayman.num_gpus = 1; ++ rdev->config.cayman.multi_gpu_tile_size = 64; ++ ++ //gb_addr_config = 0x02011003 ++#if 0 ++ gb_addr_config = RREG32(GB_ADDR_CONFIG); ++#else ++ gb_addr_config = 0; ++ switch (rdev->config.cayman.num_tile_pipes) { ++ case 1: ++ default: ++ gb_addr_config |= NUM_PIPES(0); ++ break; ++ case 2: ++ gb_addr_config |= NUM_PIPES(1); ++ break; ++ case 4: ++ gb_addr_config |= NUM_PIPES(2); ++ break; ++ case 8: ++ gb_addr_config |= NUM_PIPES(3); ++ break; ++ } ++ ++ tmp = (rdev->config.cayman.mem_max_burst_length_bytes / 256) - 1; ++ gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); ++ gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.cayman.num_shader_engines - 1); ++ tmp = (rdev->config.cayman.shader_engine_tile_size / 16) - 1; ++ gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); ++ switch (rdev->config.cayman.num_gpus) { ++ case 1: ++ default: ++ gb_addr_config |= NUM_GPUS(0); ++ break; ++ case 2: ++ gb_addr_config |= NUM_GPUS(1); ++ break; ++ case 4: ++ gb_addr_config |= NUM_GPUS(2); ++ break; ++ } ++ switch (rdev->config.cayman.multi_gpu_tile_size) { ++ case 16: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(0); ++ break; ++ case 32: ++ default: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(1); ++ break; ++ case 64: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(2); ++ break; ++ case 128: ++ gb_addr_config |= MULTI_GPU_TILE_SIZE(3); ++ break; ++ } ++ switch (rdev->config.cayman.mem_row_size_in_kb) { ++ case 1: ++ default: ++ gb_addr_config |= ROW_SIZE(0); ++ break; ++ case 2: ++ gb_addr_config |= ROW_SIZE(1); ++ break; ++ case 4: ++ gb_addr_config |= ROW_SIZE(2); ++ break; ++ } ++#endif ++ ++ tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; ++ rdev->config.cayman.num_tile_pipes = (1 << tmp); ++ tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; ++ rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; ++ tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; ++ rdev->config.cayman.num_shader_engines = tmp + 1; ++ tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; ++ rdev->config.cayman.num_gpus = tmp + 1; ++ tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; ++ rdev->config.cayman.multi_gpu_tile_size = 1 << tmp; ++ tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; ++ rdev->config.cayman.mem_row_size_in_kb = 1 << tmp; ++ ++ //gb_backend_map = 0x76541032; ++#if 0 ++ gb_backend_map = RREG32(GB_BACKEND_MAP); ++#else ++ gb_backend_map = ++ cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, ++ rdev->config.cayman.num_backends_per_se * ++ rdev->config.cayman.num_shader_engines, ++ &rdev->config.cayman.backend_disable_mask_per_asic, ++ rdev->config.cayman.num_shader_engines); ++#endif ++ /* setup tiling info dword. gb_addr_config is not adequate since it does ++ * not have bank info, so create a custom tiling dword. ++ * bits 3:0 num_pipes ++ * bits 7:4 num_banks ++ * bits 11:8 group_size ++ * bits 15:12 row_size ++ */ ++ rdev->config.cayman.tile_config = 0; ++ switch (rdev->config.cayman.num_tile_pipes) { ++ case 1: ++ default: ++ rdev->config.cayman.tile_config |= (0 << 0); ++ break; ++ case 2: ++ rdev->config.cayman.tile_config |= (1 << 0); ++ break; ++ case 4: ++ rdev->config.cayman.tile_config |= (2 << 0); ++ break; ++ case 8: ++ rdev->config.cayman.tile_config |= (3 << 0); ++ break; ++ } ++ rdev->config.cayman.tile_config |= ++ ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; ++ rdev->config.cayman.tile_config |= ++ (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; ++ rdev->config.cayman.tile_config |= ++ ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; ++ ++ WREG32(GB_BACKEND_MAP, gb_backend_map); ++ WREG32(GB_ADDR_CONFIG, gb_addr_config); ++ WREG32(DMIF_ADDR_CONFIG, gb_addr_config); ++ WREG32(HDP_ADDR_CONFIG, gb_addr_config); ++ ++ cayman_program_channel_remap(rdev); ++ ++ /* primary versions */ ++ WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); ++ ++ WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); ++ WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable); ++ ++ /* user versions */ ++ WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); ++ WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); ++ ++ WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable); ++ WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); ++ ++ /* reprogram the shader complex */ ++ cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG); ++ for (i = 0; i < 16; i++) ++ WREG32(CGTS_SM_CTRL_REG, OVERRIDE); ++ WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg); ++ ++ /* set HW defaults for 3D engine */ ++ WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); ++ ++ sx_debug_1 = RREG32(SX_DEBUG_1); ++ sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; ++ WREG32(SX_DEBUG_1, sx_debug_1); ++ ++ smx_dc_ctl0 = RREG32(SMX_DC_CTL0); ++ smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); ++ smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); ++ WREG32(SMX_DC_CTL0, smx_dc_ctl0); ++ ++ WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE); ++ ++ /* need to be explicitly zero-ed */ ++ WREG32(VGT_OFFCHIP_LDS_BASE, 0); ++ WREG32(SQ_LSTMP_RING_BASE, 0); ++ WREG32(SQ_HSTMP_RING_BASE, 0); ++ WREG32(SQ_ESTMP_RING_BASE, 0); ++ WREG32(SQ_GSTMP_RING_BASE, 0); ++ WREG32(SQ_VSTMP_RING_BASE, 0); ++ WREG32(SQ_PSTMP_RING_BASE, 0); ++ ++ WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO); ++ ++ WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | ++ POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | ++ SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); ++ ++ WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) | ++ SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) | ++ SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size))); ++ ++ ++ WREG32(VGT_NUM_INSTANCES, 1); ++ ++ WREG32(CP_PERFMON_CNTL, 0); ++ ++ WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) | ++ FETCH_FIFO_HIWATER(0x4) | ++ DONE_FIFO_HIWATER(0xe0) | ++ ALU_UPDATE_FIFO_HIWATER(0x8))); ++ ++ WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4)); ++ WREG32(SQ_CONFIG, (VC_ENABLE | ++ EXPORT_SRC_C | ++ GFX_PRIO(0) | ++ CS1_PRIO(0) | ++ CS2_PRIO(1))); ++ WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE); ++ ++ WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | ++ FORCE_EOV_MAX_REZ_CNT(255))); ++ ++ WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | ++ AUTO_INVLD_EN(ES_AND_GS_AUTO)); ++ ++ WREG32(VGT_GS_VERTEX_REUSE, 16); ++ WREG32(PA_SC_LINE_STIPPLE_STATE, 0); ++ ++ WREG32(CB_PERF_CTR0_SEL_0, 0); ++ WREG32(CB_PERF_CTR0_SEL_1, 0); ++ WREG32(CB_PERF_CTR1_SEL_0, 0); ++ WREG32(CB_PERF_CTR1_SEL_1, 0); ++ WREG32(CB_PERF_CTR2_SEL_0, 0); ++ WREG32(CB_PERF_CTR2_SEL_1, 0); ++ WREG32(CB_PERF_CTR3_SEL_0, 0); ++ WREG32(CB_PERF_CTR3_SEL_1, 0); ++ ++ hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); ++ WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); ++ ++ WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); ++ ++ udelay(50); ++} ++ ++/* ++ * GART ++ */ ++void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev) ++{ ++ /* flush hdp cache */ ++ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); ++ ++ /* bits 0-7 are the VM contexts0-7 */ ++ WREG32(VM_INVALIDATE_REQUEST, 1); ++} ++ ++int cayman_pcie_gart_enable(struct radeon_device *rdev) ++{ ++ int r; ++ ++ if (rdev->gart.table.vram.robj == NULL) { ++ dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); ++ return -EINVAL; ++ } ++ r = radeon_gart_table_vram_pin(rdev); ++ if (r) ++ return r; ++ radeon_gart_restore(rdev); ++ /* Setup TLB control */ ++ WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB | ++ ENABLE_L1_FRAGMENT_PROCESSING | ++ SYSTEM_ACCESS_MODE_NOT_IN_SYS | ++ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); ++ /* Setup L2 cache */ ++ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ++ ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | ++ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | ++ EFFECTIVE_L2_QUEUE_SIZE(7) | ++ CONTEXT1_IDENTITY_ACCESS_MODE(1)); ++ WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); ++ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | ++ L2_CACHE_BIGK_FRAGMENT_SIZE(6)); ++ /* setup context0 */ ++ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); ++ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); ++ WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, ++ (u32)(rdev->dummy_page.addr >> 12)); ++ WREG32(VM_CONTEXT0_CNTL2, 0); ++ WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); ++ /* disable context1-7 */ ++ WREG32(VM_CONTEXT1_CNTL2, 0); ++ WREG32(VM_CONTEXT1_CNTL, 0); ++ ++ cayman_pcie_gart_tlb_flush(rdev); ++ rdev->gart.ready = true; ++ return 0; ++} ++ ++void cayman_pcie_gart_disable(struct radeon_device *rdev) ++{ ++ int r; ++ ++ /* Disable all tables */ ++ WREG32(VM_CONTEXT0_CNTL, 0); ++ WREG32(VM_CONTEXT1_CNTL, 0); ++ /* Setup TLB control */ ++ WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING | ++ SYSTEM_ACCESS_MODE_NOT_IN_SYS | ++ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); ++ /* Setup L2 cache */ ++ WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | ++ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | ++ EFFECTIVE_L2_QUEUE_SIZE(7) | ++ CONTEXT1_IDENTITY_ACCESS_MODE(1)); ++ WREG32(VM_L2_CNTL2, 0); ++ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | ++ L2_CACHE_BIGK_FRAGMENT_SIZE(6)); ++ if (rdev->gart.table.vram.robj) { ++ r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); ++ if (likely(r == 0)) { ++ radeon_bo_kunmap(rdev->gart.table.vram.robj); ++ radeon_bo_unpin(rdev->gart.table.vram.robj); ++ radeon_bo_unreserve(rdev->gart.table.vram.robj); ++ } ++ } ++} ++ ++void cayman_pcie_gart_fini(struct radeon_device *rdev) ++{ ++ cayman_pcie_gart_disable(rdev); ++ radeon_gart_table_vram_free(rdev); ++ radeon_gart_fini(rdev); ++} ++ ++/* ++ * CP. ++ */ ++static void cayman_cp_enable(struct radeon_device *rdev, bool enable) ++{ ++ if (enable) ++ WREG32(CP_ME_CNTL, 0); ++ else { ++ radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); ++ WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); ++ WREG32(SCRATCH_UMSK, 0); ++ } ++} ++ ++static int cayman_cp_load_microcode(struct radeon_device *rdev) ++{ ++ const __be32 *fw_data; ++ int i; ++ ++ if (!rdev->me_fw || !rdev->pfp_fw) ++ return -EINVAL; ++ ++ cayman_cp_enable(rdev, false); ++ ++ fw_data = (const __be32 *)rdev->pfp_fw->data; ++ WREG32(CP_PFP_UCODE_ADDR, 0); ++ for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++) ++ WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); ++ WREG32(CP_PFP_UCODE_ADDR, 0); ++ ++ fw_data = (const __be32 *)rdev->me_fw->data; ++ WREG32(CP_ME_RAM_WADDR, 0); ++ for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++) ++ WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); ++ ++ WREG32(CP_PFP_UCODE_ADDR, 0); ++ WREG32(CP_ME_RAM_WADDR, 0); ++ WREG32(CP_ME_RAM_RADDR, 0); ++ return 0; ++} ++ ++static int cayman_cp_start(struct radeon_device *rdev) ++{ ++ int r, i; ++ ++ r = radeon_ring_lock(rdev, 7); ++ if (r) { ++ DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); ++ return r; ++ } ++ radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); ++ radeon_ring_write(rdev, 0x1); ++ radeon_ring_write(rdev, 0x0); ++ radeon_ring_write(rdev, rdev->config.cayman.max_hw_contexts - 1); ++ radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); ++ radeon_ring_write(rdev, 0); ++ radeon_ring_write(rdev, 0); ++ radeon_ring_unlock_commit(rdev); ++ ++ cayman_cp_enable(rdev, true); ++ ++ r = radeon_ring_lock(rdev, cayman_default_size + 19); ++ if (r) { ++ DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); ++ return r; ++ } ++ ++ /* setup clear context state */ ++ radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); ++ ++ for (i = 0; i < cayman_default_size; i++) ++ radeon_ring_write(rdev, cayman_default_state[i]); ++ ++ radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); ++ radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE); ++ ++ /* set clear context state */ ++ radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); ++ radeon_ring_write(rdev, 0); ++ ++ /* SQ_VTX_BASE_VTX_LOC */ ++ radeon_ring_write(rdev, 0xc0026f00); ++ radeon_ring_write(rdev, 0x00000000); ++ radeon_ring_write(rdev, 0x00000000); ++ radeon_ring_write(rdev, 0x00000000); ++ ++ /* Clear consts */ ++ radeon_ring_write(rdev, 0xc0036f00); ++ radeon_ring_write(rdev, 0x00000bc4); ++ radeon_ring_write(rdev, 0xffffffff); ++ radeon_ring_write(rdev, 0xffffffff); ++ radeon_ring_write(rdev, 0xffffffff); ++ ++ radeon_ring_write(rdev, 0xc0026900); ++ radeon_ring_write(rdev, 0x00000316); ++ radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ ++ radeon_ring_write(rdev, 0x00000010); /* */ ++ ++ radeon_ring_unlock_commit(rdev); ++ ++ /* XXX init other rings */ ++ ++ return 0; ++} ++ ++static void cayman_cp_fini(struct radeon_device *rdev) ++{ ++ cayman_cp_enable(rdev, false); ++ radeon_ring_fini(rdev); ++} ++ ++int cayman_cp_resume(struct radeon_device *rdev) ++{ ++ u32 tmp; ++ u32 rb_bufsz; ++ int r; ++ ++ /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ ++ WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | ++ SOFT_RESET_PA | ++ SOFT_RESET_SH | ++ SOFT_RESET_VGT | ++ SOFT_RESET_SX)); ++ RREG32(GRBM_SOFT_RESET); ++ mdelay(15); ++ WREG32(GRBM_SOFT_RESET, 0); ++ RREG32(GRBM_SOFT_RESET); ++ ++ WREG32(CP_SEM_WAIT_TIMER, 0x4); ++ ++ /* Set the write pointer delay */ ++ WREG32(CP_RB_WPTR_DELAY, 0); ++ ++ WREG32(CP_DEBUG, (1 << 27)); ++ ++ /* ring 0 - compute and gfx */ ++ /* Set ring buffer size */ ++ rb_bufsz = drm_order(rdev->cp.ring_size / 8); ++ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; ++#ifdef __BIG_ENDIAN ++ tmp |= BUF_SWAP_32BIT; ++#endif ++ WREG32(CP_RB0_CNTL, tmp); ++ ++ /* Initialize the ring buffer's read and write pointers */ ++ WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); ++ WREG32(CP_RB0_WPTR, 0); ++ ++ /* set the wb address wether it's enabled or not */ ++ WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); ++ WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); ++ WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); ++ ++ if (rdev->wb.enabled) ++ WREG32(SCRATCH_UMSK, 0xff); ++ else { ++ tmp |= RB_NO_UPDATE; ++ WREG32(SCRATCH_UMSK, 0); ++ } ++ ++ mdelay(1); ++ WREG32(CP_RB0_CNTL, tmp); ++ ++ WREG32(CP_RB0_BASE, rdev->cp.gpu_addr >> 8); ++ ++ rdev->cp.rptr = RREG32(CP_RB0_RPTR); ++ rdev->cp.wptr = RREG32(CP_RB0_WPTR); ++ ++ /* ring1 - compute only */ ++ /* Set ring buffer size */ ++ rb_bufsz = drm_order(rdev->cp1.ring_size / 8); ++ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; ++#ifdef __BIG_ENDIAN ++ tmp |= BUF_SWAP_32BIT; ++#endif ++ WREG32(CP_RB1_CNTL, tmp); ++ ++ /* Initialize the ring buffer's read and write pointers */ ++ WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); ++ WREG32(CP_RB1_WPTR, 0); ++ ++ /* set the wb address wether it's enabled or not */ ++ WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); ++ WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); ++ ++ mdelay(1); ++ WREG32(CP_RB1_CNTL, tmp); ++ ++ WREG32(CP_RB1_BASE, rdev->cp1.gpu_addr >> 8); ++ ++ rdev->cp1.rptr = RREG32(CP_RB1_RPTR); ++ rdev->cp1.wptr = RREG32(CP_RB1_WPTR); ++ ++ /* ring2 - compute only */ ++ /* Set ring buffer size */ ++ rb_bufsz = drm_order(rdev->cp2.ring_size / 8); ++ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; ++#ifdef __BIG_ENDIAN ++ tmp |= BUF_SWAP_32BIT; ++#endif ++ WREG32(CP_RB2_CNTL, tmp); ++ ++ /* Initialize the ring buffer's read and write pointers */ ++ WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); ++ WREG32(CP_RB2_WPTR, 0); ++ ++ /* set the wb address wether it's enabled or not */ ++ WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); ++ WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); ++ ++ mdelay(1); ++ WREG32(CP_RB2_CNTL, tmp); ++ ++ WREG32(CP_RB2_BASE, rdev->cp2.gpu_addr >> 8); ++ ++ rdev->cp2.rptr = RREG32(CP_RB2_RPTR); ++ rdev->cp2.wptr = RREG32(CP_RB2_WPTR); ++ ++ /* start the rings */ ++ cayman_cp_start(rdev); ++ rdev->cp.ready = true; ++ rdev->cp1.ready = true; ++ rdev->cp2.ready = true; ++ /* this only test cp0 */ ++ r = radeon_ring_test(rdev); ++ if (r) { ++ rdev->cp.ready = false; ++ rdev->cp1.ready = false; ++ rdev->cp2.ready = false; ++ return r; ++ } ++ ++ return 0; ++} ++ ++bool cayman_gpu_is_lockup(struct radeon_device *rdev) ++{ ++ u32 srbm_status; ++ u32 grbm_status; ++ u32 grbm_status_se0, grbm_status_se1; ++ struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup; ++ int r; ++ ++ srbm_status = RREG32(SRBM_STATUS); ++ grbm_status = RREG32(GRBM_STATUS); ++ grbm_status_se0 = RREG32(GRBM_STATUS_SE0); ++ grbm_status_se1 = RREG32(GRBM_STATUS_SE1); ++ if (!(grbm_status & GUI_ACTIVE)) { ++ r100_gpu_lockup_update(lockup, &rdev->cp); ++ return false; ++ } ++ /* force CP activities */ ++ r = radeon_ring_lock(rdev, 2); ++ if (!r) { ++ /* PACKET2 NOP */ ++ radeon_ring_write(rdev, 0x80000000); ++ radeon_ring_write(rdev, 0x80000000); ++ radeon_ring_unlock_commit(rdev); ++ } ++ /* XXX deal with CP0,1,2 */ ++ rdev->cp.rptr = RREG32(CP_RB0_RPTR); ++ return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); ++} ++ ++static int cayman_gpu_soft_reset(struct radeon_device *rdev) ++{ ++ struct evergreen_mc_save save; ++ u32 grbm_reset = 0; ++ ++ if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) ++ return 0; ++ ++ dev_info(rdev->dev, "GPU softreset \n"); ++ dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", ++ RREG32(GRBM_STATUS)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", ++ RREG32(GRBM_STATUS_SE0)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", ++ RREG32(GRBM_STATUS_SE1)); ++ dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", ++ RREG32(SRBM_STATUS)); ++ evergreen_mc_stop(rdev, &save); ++ if (evergreen_mc_wait_for_idle(rdev)) { ++ dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); ++ } ++ /* Disable CP parsing/prefetching */ ++ WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); ++ ++ /* reset all the gfx blocks */ ++ grbm_reset = (SOFT_RESET_CP | ++ SOFT_RESET_CB | ++ SOFT_RESET_DB | ++ SOFT_RESET_GDS | ++ SOFT_RESET_PA | ++ SOFT_RESET_SC | ++ SOFT_RESET_SPI | ++ SOFT_RESET_SH | ++ SOFT_RESET_SX | ++ SOFT_RESET_TC | ++ SOFT_RESET_TA | ++ SOFT_RESET_VGT | ++ SOFT_RESET_IA); ++ ++ dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); ++ WREG32(GRBM_SOFT_RESET, grbm_reset); ++ (void)RREG32(GRBM_SOFT_RESET); ++ udelay(50); ++ WREG32(GRBM_SOFT_RESET, 0); ++ (void)RREG32(GRBM_SOFT_RESET); ++ /* Wait a little for things to settle down */ ++ udelay(50); ++ dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", ++ RREG32(GRBM_STATUS)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", ++ RREG32(GRBM_STATUS_SE0)); ++ dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", ++ RREG32(GRBM_STATUS_SE1)); ++ dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", ++ RREG32(SRBM_STATUS)); ++ evergreen_mc_resume(rdev, &save); ++ return 0; ++} ++ ++int cayman_asic_reset(struct radeon_device *rdev) ++{ ++ return cayman_gpu_soft_reset(rdev); ++} ++ ++static int cayman_startup(struct radeon_device *rdev) ++{ ++ int r; ++ ++ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { ++ r = ni_init_microcode(rdev); ++ if (r) { ++ DRM_ERROR("Failed to load firmware!\n"); ++ return r; ++ } ++ } ++ r = ni_mc_load_microcode(rdev); ++ if (r) { ++ DRM_ERROR("Failed to load MC firmware!\n"); ++ return r; ++ } ++ ++ evergreen_mc_program(rdev); ++ r = cayman_pcie_gart_enable(rdev); ++ if (r) ++ return r; ++ cayman_gpu_init(rdev); ++ ++#if 0 ++ r = cayman_blit_init(rdev); ++ if (r) { ++ cayman_blit_fini(rdev); ++ rdev->asic->copy = NULL; ++ dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); ++ } ++#endif ++ ++ /* allocate wb buffer */ ++ r = radeon_wb_init(rdev); ++ if (r) ++ return r; ++ ++ /* Enable IRQ */ ++ r = r600_irq_init(rdev); ++ if (r) { ++ DRM_ERROR("radeon: IH init failed (%d).\n", r); ++ radeon_irq_kms_fini(rdev); ++ return r; ++ } ++ evergreen_irq_set(rdev); ++ ++ r = radeon_ring_init(rdev, rdev->cp.ring_size); ++ if (r) ++ return r; ++ r = cayman_cp_load_microcode(rdev); ++ if (r) ++ return r; ++ r = cayman_cp_resume(rdev); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++int cayman_resume(struct radeon_device *rdev) ++{ ++ int r; ++ ++ /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, ++ * posting will perform necessary task to bring back GPU into good ++ * shape. ++ */ ++ /* post card */ ++ atom_asic_init(rdev->mode_info.atom_context); ++ ++ r = cayman_startup(rdev); ++ if (r) { ++ DRM_ERROR("cayman startup failed on resume\n"); ++ return r; ++ } ++ ++ r = r600_ib_test(rdev); ++ if (r) { ++ DRM_ERROR("radeon: failled testing IB (%d).\n", r); ++ return r; ++ } ++ ++ return r; ++ ++} ++ ++int cayman_suspend(struct radeon_device *rdev) ++{ ++ /* int r; */ ++ ++ /* FIXME: we should wait for ring to be empty */ ++ cayman_cp_enable(rdev, false); ++ rdev->cp.ready = false; ++ evergreen_irq_suspend(rdev); ++ radeon_wb_disable(rdev); ++ cayman_pcie_gart_disable(rdev); ++ ++#if 0 ++ /* unpin shaders bo */ ++ r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); ++ if (likely(r == 0)) { ++ radeon_bo_unpin(rdev->r600_blit.shader_obj); ++ radeon_bo_unreserve(rdev->r600_blit.shader_obj); ++ } ++#endif ++ return 0; ++} ++ ++/* Plan is to move initialization in that function and use ++ * helper function so that radeon_device_init pretty much ++ * do nothing more than calling asic specific function. This ++ * should also allow to remove a bunch of callback function ++ * like vram_info. ++ */ ++int cayman_init(struct radeon_device *rdev) ++{ ++ int r; ++ ++ /* This don't do much */ ++ r = radeon_gem_init(rdev); ++ if (r) ++ return r; ++ /* Read BIOS */ ++ if (!radeon_get_bios(rdev)) { ++ if (ASIC_IS_AVIVO(rdev)) ++ return -EINVAL; ++ } ++ /* Must be an ATOMBIOS */ ++ if (!rdev->is_atom_bios) { ++ dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); ++ return -EINVAL; ++ } ++ r = radeon_atombios_init(rdev); ++ if (r) ++ return r; ++ ++ /* Post card if necessary */ ++ if (!radeon_card_posted(rdev)) { ++ if (!rdev->bios) { ++ dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); ++ return -EINVAL; ++ } ++ DRM_INFO("GPU not posted. posting now...\n"); ++ atom_asic_init(rdev->mode_info.atom_context); ++ } ++ /* Initialize scratch registers */ ++ r600_scratch_init(rdev); ++ /* Initialize surface registers */ ++ radeon_surface_init(rdev); ++ /* Initialize clocks */ ++ radeon_get_clock_info(rdev->ddev); ++ /* Fence driver */ ++ r = radeon_fence_driver_init(rdev); ++ if (r) ++ return r; ++ /* initialize memory controller */ ++ r = evergreen_mc_init(rdev); ++ if (r) ++ return r; ++ /* Memory manager */ ++ r = radeon_bo_init(rdev); ++ if (r) ++ return r; ++ ++ r = radeon_irq_kms_init(rdev); ++ if (r) ++ return r; ++ ++ rdev->cp.ring_obj = NULL; ++ r600_ring_init(rdev, 1024 * 1024); ++ ++ rdev->ih.ring_obj = NULL; ++ r600_ih_ring_init(rdev, 64 * 1024); ++ ++ r = r600_pcie_gart_init(rdev); ++ if (r) ++ return r; ++ ++ rdev->accel_working = true; ++ r = cayman_startup(rdev); ++ if (r) { ++ dev_err(rdev->dev, "disabling GPU acceleration\n"); ++ cayman_cp_fini(rdev); ++ r600_irq_fini(rdev); ++ radeon_wb_fini(rdev); ++ radeon_irq_kms_fini(rdev); ++ cayman_pcie_gart_fini(rdev); ++ rdev->accel_working = false; ++ } ++ if (rdev->accel_working) { ++ r = radeon_ib_pool_init(rdev); ++ if (r) { ++ DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ r = r600_ib_test(rdev); ++ if (r) { ++ DRM_ERROR("radeon: failed testing IB (%d).\n", r); ++ rdev->accel_working = false; ++ } ++ } ++ ++ /* Don't start up if the MC ucode is missing. ++ * The default clocks and voltages before the MC ucode ++ * is loaded are not suffient for advanced operations. ++ */ ++ if (!rdev->mc_fw) { ++ DRM_ERROR("radeon: MC ucode required for NI+.\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void cayman_fini(struct radeon_device *rdev) ++{ ++ /* cayman_blit_fini(rdev); */ ++ cayman_cp_fini(rdev); ++ r600_irq_fini(rdev); ++ radeon_wb_fini(rdev); ++ radeon_irq_kms_fini(rdev); ++ cayman_pcie_gart_fini(rdev); ++ radeon_gem_fini(rdev); ++ radeon_fence_driver_fini(rdev); ++ radeon_bo_fini(rdev); ++ radeon_atombios_fini(rdev); ++ kfree(rdev->bios); ++ rdev->bios = NULL; ++} ++ +diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h +index f7b4453..0f9a08b 100644 +--- a/drivers/gpu/drm/radeon/nid.h ++++ b/drivers/gpu/drm/radeon/nid.h +@@ -24,7 +24,101 @@ + #ifndef NI_H + #define NI_H + ++#define CAYMAN_MAX_SH_GPRS 256 ++#define CAYMAN_MAX_TEMP_GPRS 16 ++#define CAYMAN_MAX_SH_THREADS 256 ++#define CAYMAN_MAX_SH_STACK_ENTRIES 4096 ++#define CAYMAN_MAX_FRC_EOV_CNT 16384 ++#define CAYMAN_MAX_BACKENDS 8 ++#define CAYMAN_MAX_BACKENDS_MASK 0xFF ++#define CAYMAN_MAX_BACKENDS_PER_SE_MASK 0xF ++#define CAYMAN_MAX_SIMDS 16 ++#define CAYMAN_MAX_SIMDS_MASK 0xFFFF ++#define CAYMAN_MAX_SIMDS_PER_SE_MASK 0xFFF ++#define CAYMAN_MAX_PIPES 8 ++#define CAYMAN_MAX_PIPES_MASK 0xFF ++#define CAYMAN_MAX_LDS_NUM 0xFFFF ++#define CAYMAN_MAX_TCC 16 ++#define CAYMAN_MAX_TCC_MASK 0xFF ++ ++#define DMIF_ADDR_CONFIG 0xBD4 ++#define SRBM_STATUS 0x0E50 ++ ++#define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 ++#define REQUEST_TYPE(x) (((x) & 0xf) << 0) ++#define RESPONSE_TYPE_MASK 0x000000F0 ++#define RESPONSE_TYPE_SHIFT 4 ++#define VM_L2_CNTL 0x1400 ++#define ENABLE_L2_CACHE (1 << 0) ++#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) ++#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) ++#define ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE (1 << 10) ++#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 14) ++#define CONTEXT1_IDENTITY_ACCESS_MODE(x) (((x) & 3) << 18) ++/* CONTEXT1_IDENTITY_ACCESS_MODE ++ * 0 physical = logical ++ * 1 logical via context1 page table ++ * 2 inside identity aperture use translation, outside physical = logical ++ * 3 inside identity aperture physical = logical, outside use translation ++ */ ++#define VM_L2_CNTL2 0x1404 ++#define INVALIDATE_ALL_L1_TLBS (1 << 0) ++#define INVALIDATE_L2_CACHE (1 << 1) ++#define VM_L2_CNTL3 0x1408 ++#define BANK_SELECT(x) ((x) << 0) ++#define CACHE_UPDATE_MODE(x) ((x) << 6) ++#define L2_CACHE_BIGK_ASSOCIATIVITY (1 << 20) ++#define L2_CACHE_BIGK_FRAGMENT_SIZE(x) ((x) << 15) ++#define VM_L2_STATUS 0x140C ++#define L2_BUSY (1 << 0) ++#define VM_CONTEXT0_CNTL 0x1410 ++#define ENABLE_CONTEXT (1 << 0) ++#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) ++#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) ++#define VM_CONTEXT1_CNTL 0x1414 ++#define VM_CONTEXT0_CNTL2 0x1430 ++#define VM_CONTEXT1_CNTL2 0x1434 ++#define VM_INVALIDATE_REQUEST 0x1478 ++#define VM_INVALIDATE_RESPONSE 0x147c ++#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 ++#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c ++#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C ++#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C ++#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C ++ ++#define MC_SHARED_CHMAP 0x2004 ++#define NOOFCHAN_SHIFT 12 ++#define NOOFCHAN_MASK 0x00003000 ++#define MC_SHARED_CHREMAP 0x2008 ++ ++#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 ++#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 ++#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C ++#define MC_VM_MX_L1_TLB_CNTL 0x2064 ++#define ENABLE_L1_TLB (1 << 0) ++#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) ++#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) ++#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) ++#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) ++#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) ++#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) ++#define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) ++ + #define MC_SHARED_BLACKOUT_CNTL 0x20ac ++#define MC_ARB_RAMCFG 0x2760 ++#define NOOFBANK_SHIFT 0 ++#define NOOFBANK_MASK 0x00000003 ++#define NOOFRANK_SHIFT 2 ++#define NOOFRANK_MASK 0x00000004 ++#define NOOFROWS_SHIFT 3 ++#define NOOFROWS_MASK 0x00000038 ++#define NOOFCOLS_SHIFT 6 ++#define NOOFCOLS_MASK 0x000000C0 ++#define CHANSIZE_SHIFT 8 ++#define CHANSIZE_MASK 0x00000100 ++#define BURSTLENGTH_SHIFT 9 ++#define BURSTLENGTH_MASK 0x00000200 ++#define CHANSIZE_OVERRIDE (1 << 11) + #define MC_SEQ_SUP_CNTL 0x28c8 + #define RUN_MASK (1 << 0) + #define MC_SEQ_SUP_PGM 0x28cc +@@ -37,5 +131,406 @@ + #define MC_SEQ_IO_DEBUG_INDEX 0x2a44 + #define MC_SEQ_IO_DEBUG_DATA 0x2a48 + ++#define HDP_HOST_PATH_CNTL 0x2C00 ++#define HDP_NONSURFACE_BASE 0x2C04 ++#define HDP_NONSURFACE_INFO 0x2C08 ++#define HDP_NONSURFACE_SIZE 0x2C0C ++#define HDP_ADDR_CONFIG 0x2F48 ++ ++#define CC_SYS_RB_BACKEND_DISABLE 0x3F88 ++#define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C ++#define CGTS_SYS_TCC_DISABLE 0x3F90 ++#define CGTS_USER_SYS_TCC_DISABLE 0x3F94 ++ ++#define CONFIG_MEMSIZE 0x5428 ++ ++#define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 ++#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 ++ ++#define GRBM_CNTL 0x8000 ++#define GRBM_READ_TIMEOUT(x) ((x) << 0) ++#define GRBM_STATUS 0x8010 ++#define CMDFIFO_AVAIL_MASK 0x0000000F ++#define RING2_RQ_PENDING (1 << 4) ++#define SRBM_RQ_PENDING (1 << 5) ++#define RING1_RQ_PENDING (1 << 6) ++#define CF_RQ_PENDING (1 << 7) ++#define PF_RQ_PENDING (1 << 8) ++#define GDS_DMA_RQ_PENDING (1 << 9) ++#define GRBM_EE_BUSY (1 << 10) ++#define SX_CLEAN (1 << 11) ++#define DB_CLEAN (1 << 12) ++#define CB_CLEAN (1 << 13) ++#define TA_BUSY (1 << 14) ++#define GDS_BUSY (1 << 15) ++#define VGT_BUSY_NO_DMA (1 << 16) ++#define VGT_BUSY (1 << 17) ++#define IA_BUSY_NO_DMA (1 << 18) ++#define IA_BUSY (1 << 19) ++#define SX_BUSY (1 << 20) ++#define SH_BUSY (1 << 21) ++#define SPI_BUSY (1 << 22) ++#define SC_BUSY (1 << 24) ++#define PA_BUSY (1 << 25) ++#define DB_BUSY (1 << 26) ++#define CP_COHERENCY_BUSY (1 << 28) ++#define CP_BUSY (1 << 29) ++#define CB_BUSY (1 << 30) ++#define GUI_ACTIVE (1 << 31) ++#define GRBM_STATUS_SE0 0x8014 ++#define GRBM_STATUS_SE1 0x8018 ++#define SE_SX_CLEAN (1 << 0) ++#define SE_DB_CLEAN (1 << 1) ++#define SE_CB_CLEAN (1 << 2) ++#define SE_VGT_BUSY (1 << 23) ++#define SE_PA_BUSY (1 << 24) ++#define SE_TA_BUSY (1 << 25) ++#define SE_SX_BUSY (1 << 26) ++#define SE_SPI_BUSY (1 << 27) ++#define SE_SH_BUSY (1 << 28) ++#define SE_SC_BUSY (1 << 29) ++#define SE_DB_BUSY (1 << 30) ++#define SE_CB_BUSY (1 << 31) ++#define GRBM_SOFT_RESET 0x8020 ++#define SOFT_RESET_CP (1 << 0) ++#define SOFT_RESET_CB (1 << 1) ++#define SOFT_RESET_DB (1 << 3) ++#define SOFT_RESET_GDS (1 << 4) ++#define SOFT_RESET_PA (1 << 5) ++#define SOFT_RESET_SC (1 << 6) ++#define SOFT_RESET_SPI (1 << 8) ++#define SOFT_RESET_SH (1 << 9) ++#define SOFT_RESET_SX (1 << 10) ++#define SOFT_RESET_TC (1 << 11) ++#define SOFT_RESET_TA (1 << 12) ++#define SOFT_RESET_VGT (1 << 14) ++#define SOFT_RESET_IA (1 << 15) ++ ++#define SCRATCH_REG0 0x8500 ++#define SCRATCH_REG1 0x8504 ++#define SCRATCH_REG2 0x8508 ++#define SCRATCH_REG3 0x850C ++#define SCRATCH_REG4 0x8510 ++#define SCRATCH_REG5 0x8514 ++#define SCRATCH_REG6 0x8518 ++#define SCRATCH_REG7 0x851C ++#define SCRATCH_UMSK 0x8540 ++#define SCRATCH_ADDR 0x8544 ++#define CP_SEM_WAIT_TIMER 0x85BC ++#define CP_ME_CNTL 0x86D8 ++#define CP_ME_HALT (1 << 28) ++#define CP_PFP_HALT (1 << 26) ++#define CP_RB2_RPTR 0x86f8 ++#define CP_RB1_RPTR 0x86fc ++#define CP_RB0_RPTR 0x8700 ++#define CP_RB_WPTR_DELAY 0x8704 ++#define CP_MEQ_THRESHOLDS 0x8764 ++#define MEQ1_START(x) ((x) << 0) ++#define MEQ2_START(x) ((x) << 8) ++#define CP_PERFMON_CNTL 0x87FC ++ ++#define VGT_CACHE_INVALIDATION 0x88C4 ++#define CACHE_INVALIDATION(x) ((x) << 0) ++#define VC_ONLY 0 ++#define TC_ONLY 1 ++#define VC_AND_TC 2 ++#define AUTO_INVLD_EN(x) ((x) << 6) ++#define NO_AUTO 0 ++#define ES_AUTO 1 ++#define GS_AUTO 2 ++#define ES_AND_GS_AUTO 3 ++#define VGT_GS_VERTEX_REUSE 0x88D4 ++ ++#define CC_GC_SHADER_PIPE_CONFIG 0x8950 ++#define GC_USER_SHADER_PIPE_CONFIG 0x8954 ++#define INACTIVE_QD_PIPES(x) ((x) << 8) ++#define INACTIVE_QD_PIPES_MASK 0x0000FF00 ++#define INACTIVE_QD_PIPES_SHIFT 8 ++#define INACTIVE_SIMDS(x) ((x) << 16) ++#define INACTIVE_SIMDS_MASK 0xFFFF0000 ++#define INACTIVE_SIMDS_SHIFT 16 ++ ++#define VGT_PRIMITIVE_TYPE 0x8958 ++#define VGT_NUM_INSTANCES 0x8974 ++#define VGT_TF_RING_SIZE 0x8988 ++#define VGT_OFFCHIP_LDS_BASE 0x89b4 ++ ++#define PA_SC_LINE_STIPPLE_STATE 0x8B10 ++#define PA_CL_ENHANCE 0x8A14 ++#define CLIP_VTX_REORDER_ENA (1 << 0) ++#define NUM_CLIP_SEQ(x) ((x) << 1) ++#define PA_SC_FIFO_SIZE 0x8BCC ++#define SC_PRIM_FIFO_SIZE(x) ((x) << 0) ++#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) ++#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) ++#define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 ++#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) ++#define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) ++ ++#define SQ_CONFIG 0x8C00 ++#define VC_ENABLE (1 << 0) ++#define EXPORT_SRC_C (1 << 1) ++#define GFX_PRIO(x) ((x) << 2) ++#define CS1_PRIO(x) ((x) << 4) ++#define CS2_PRIO(x) ((x) << 6) ++#define SQ_GPR_RESOURCE_MGMT_1 0x8C04 ++#define NUM_PS_GPRS(x) ((x) << 0) ++#define NUM_VS_GPRS(x) ((x) << 16) ++#define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) ++#define SQ_ESGS_RING_SIZE 0x8c44 ++#define SQ_GSVS_RING_SIZE 0x8c4c ++#define SQ_ESTMP_RING_BASE 0x8c50 ++#define SQ_ESTMP_RING_SIZE 0x8c54 ++#define SQ_GSTMP_RING_BASE 0x8c58 ++#define SQ_GSTMP_RING_SIZE 0x8c5c ++#define SQ_VSTMP_RING_BASE 0x8c60 ++#define SQ_VSTMP_RING_SIZE 0x8c64 ++#define SQ_PSTMP_RING_BASE 0x8c68 ++#define SQ_PSTMP_RING_SIZE 0x8c6c ++#define SQ_MS_FIFO_SIZES 0x8CF0 ++#define CACHE_FIFO_SIZE(x) ((x) << 0) ++#define FETCH_FIFO_HIWATER(x) ((x) << 8) ++#define DONE_FIFO_HIWATER(x) ((x) << 16) ++#define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) ++#define SQ_LSTMP_RING_BASE 0x8e10 ++#define SQ_LSTMP_RING_SIZE 0x8e14 ++#define SQ_HSTMP_RING_BASE 0x8e18 ++#define SQ_HSTMP_RING_SIZE 0x8e1c ++#define SQ_DYN_GPR_CNTL_PS_FLUSH_REQ 0x8D8C ++#define DYN_GPR_ENABLE (1 << 8) ++#define SQ_CONST_MEM_BASE 0x8df8 ++ ++#define SX_EXPORT_BUFFER_SIZES 0x900C ++#define COLOR_BUFFER_SIZE(x) ((x) << 0) ++#define POSITION_BUFFER_SIZE(x) ((x) << 8) ++#define SMX_BUFFER_SIZE(x) ((x) << 16) ++#define SX_DEBUG_1 0x9058 ++#define ENABLE_NEW_SMX_ADDRESS (1 << 16) ++ ++#define SPI_CONFIG_CNTL 0x9100 ++#define GPR_WRITE_PRIORITY(x) ((x) << 0) ++#define SPI_CONFIG_CNTL_1 0x913C ++#define VTX_DONE_DELAY(x) ((x) << 0) ++#define INTERP_ONE_PRIM_PER_ROW (1 << 4) ++#define CRC_SIMD_ID_WADDR_DISABLE (1 << 8) ++ ++#define CGTS_TCC_DISABLE 0x9148 ++#define CGTS_USER_TCC_DISABLE 0x914C ++#define TCC_DISABLE_MASK 0xFFFF0000 ++#define TCC_DISABLE_SHIFT 16 ++#define CGTS_SM_CTRL_REG 0x915C ++#define OVERRIDE (1 << 21) ++ ++#define TA_CNTL_AUX 0x9508 ++#define DISABLE_CUBE_WRAP (1 << 0) ++#define DISABLE_CUBE_ANISO (1 << 1) ++ ++#define TCP_CHAN_STEER_LO 0x960c ++#define TCP_CHAN_STEER_HI 0x9610 ++ ++#define CC_RB_BACKEND_DISABLE 0x98F4 ++#define BACKEND_DISABLE(x) ((x) << 16) ++#define GB_ADDR_CONFIG 0x98F8 ++#define NUM_PIPES(x) ((x) << 0) ++#define NUM_PIPES_MASK 0x00000007 ++#define NUM_PIPES_SHIFT 0 ++#define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) ++#define PIPE_INTERLEAVE_SIZE_MASK 0x00000070 ++#define PIPE_INTERLEAVE_SIZE_SHIFT 4 ++#define BANK_INTERLEAVE_SIZE(x) ((x) << 8) ++#define NUM_SHADER_ENGINES(x) ((x) << 12) ++#define NUM_SHADER_ENGINES_MASK 0x00003000 ++#define NUM_SHADER_ENGINES_SHIFT 12 ++#define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) ++#define SHADER_ENGINE_TILE_SIZE_MASK 0x00070000 ++#define SHADER_ENGINE_TILE_SIZE_SHIFT 16 ++#define NUM_GPUS(x) ((x) << 20) ++#define NUM_GPUS_MASK 0x00700000 ++#define NUM_GPUS_SHIFT 20 ++#define MULTI_GPU_TILE_SIZE(x) ((x) << 24) ++#define MULTI_GPU_TILE_SIZE_MASK 0x03000000 ++#define MULTI_GPU_TILE_SIZE_SHIFT 24 ++#define ROW_SIZE(x) ((x) << 28) ++#define ROW_SIZE_MASK 0x30000007 ++#define ROW_SIZE_SHIFT 28 ++#define NUM_LOWER_PIPES(x) ((x) << 30) ++#define NUM_LOWER_PIPES_MASK 0x40000000 ++#define NUM_LOWER_PIPES_SHIFT 30 ++#define GB_BACKEND_MAP 0x98FC ++ ++#define CB_PERF_CTR0_SEL_0 0x9A20 ++#define CB_PERF_CTR0_SEL_1 0x9A24 ++#define CB_PERF_CTR1_SEL_0 0x9A28 ++#define CB_PERF_CTR1_SEL_1 0x9A2C ++#define CB_PERF_CTR2_SEL_0 0x9A30 ++#define CB_PERF_CTR2_SEL_1 0x9A34 ++#define CB_PERF_CTR3_SEL_0 0x9A38 ++#define CB_PERF_CTR3_SEL_1 0x9A3C ++ ++#define GC_USER_RB_BACKEND_DISABLE 0x9B7C ++#define BACKEND_DISABLE_MASK 0x00FF0000 ++#define BACKEND_DISABLE_SHIFT 16 ++ ++#define SMX_DC_CTL0 0xA020 ++#define USE_HASH_FUNCTION (1 << 0) ++#define NUMBER_OF_SETS(x) ((x) << 1) ++#define FLUSH_ALL_ON_EVENT (1 << 10) ++#define STALL_ON_EVENT (1 << 11) ++#define SMX_EVENT_CTL 0xA02C ++#define ES_FLUSH_CTL(x) ((x) << 0) ++#define GS_FLUSH_CTL(x) ((x) << 3) ++#define ACK_FLUSH_CTL(x) ((x) << 6) ++#define SYNC_FLUSH_CTL (1 << 8) ++ ++#define CP_RB0_BASE 0xC100 ++#define CP_RB0_CNTL 0xC104 ++#define RB_BUFSZ(x) ((x) << 0) ++#define RB_BLKSZ(x) ((x) << 8) ++#define RB_NO_UPDATE (1 << 27) ++#define RB_RPTR_WR_ENA (1 << 31) ++#define BUF_SWAP_32BIT (2 << 16) ++#define CP_RB0_RPTR_ADDR 0xC10C ++#define CP_RB0_RPTR_ADDR_HI 0xC110 ++#define CP_RB0_WPTR 0xC114 ++#define CP_RB1_BASE 0xC180 ++#define CP_RB1_CNTL 0xC184 ++#define CP_RB1_RPTR_ADDR 0xC188 ++#define CP_RB1_RPTR_ADDR_HI 0xC18C ++#define CP_RB1_WPTR 0xC190 ++#define CP_RB2_BASE 0xC194 ++#define CP_RB2_CNTL 0xC198 ++#define CP_RB2_RPTR_ADDR 0xC19C ++#define CP_RB2_RPTR_ADDR_HI 0xC1A0 ++#define CP_RB2_WPTR 0xC1A4 ++#define CP_PFP_UCODE_ADDR 0xC150 ++#define CP_PFP_UCODE_DATA 0xC154 ++#define CP_ME_RAM_RADDR 0xC158 ++#define CP_ME_RAM_WADDR 0xC15C ++#define CP_ME_RAM_DATA 0xC160 ++#define CP_DEBUG 0xC1FC ++ ++/* ++ * PM4 ++ */ ++#define PACKET_TYPE0 0 ++#define PACKET_TYPE1 1 ++#define PACKET_TYPE2 2 ++#define PACKET_TYPE3 3 ++ ++#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) ++#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) ++#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) ++#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) ++#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ ++ (((reg) >> 2) & 0xFFFF) | \ ++ ((n) & 0x3FFF) << 16) ++#define CP_PACKET2 0x80000000 ++#define PACKET2_PAD_SHIFT 0 ++#define PACKET2_PAD_MASK (0x3fffffff << 0) ++ ++#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) ++ ++#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ ++ (((op) & 0xFF) << 8) | \ ++ ((n) & 0x3FFF) << 16) ++ ++/* Packet 3 types */ ++#define PACKET3_NOP 0x10 ++#define PACKET3_SET_BASE 0x11 ++#define PACKET3_CLEAR_STATE 0x12 ++#define PACKET3_INDEX_BUFFER_SIZE 0x13 ++#define PACKET3_DEALLOC_STATE 0x14 ++#define PACKET3_DISPATCH_DIRECT 0x15 ++#define PACKET3_DISPATCH_INDIRECT 0x16 ++#define PACKET3_INDIRECT_BUFFER_END 0x17 ++#define PACKET3_SET_PREDICATION 0x20 ++#define PACKET3_REG_RMW 0x21 ++#define PACKET3_COND_EXEC 0x22 ++#define PACKET3_PRED_EXEC 0x23 ++#define PACKET3_DRAW_INDIRECT 0x24 ++#define PACKET3_DRAW_INDEX_INDIRECT 0x25 ++#define PACKET3_INDEX_BASE 0x26 ++#define PACKET3_DRAW_INDEX_2 0x27 ++#define PACKET3_CONTEXT_CONTROL 0x28 ++#define PACKET3_DRAW_INDEX_OFFSET 0x29 ++#define PACKET3_INDEX_TYPE 0x2A ++#define PACKET3_DRAW_INDEX 0x2B ++#define PACKET3_DRAW_INDEX_AUTO 0x2D ++#define PACKET3_DRAW_INDEX_IMMD 0x2E ++#define PACKET3_NUM_INSTANCES 0x2F ++#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 ++#define PACKET3_INDIRECT_BUFFER 0x32 ++#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 ++#define PACKET3_DRAW_INDEX_OFFSET_2 0x35 ++#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 ++#define PACKET3_WRITE_DATA 0x37 ++#define PACKET3_MEM_SEMAPHORE 0x39 ++#define PACKET3_MPEG_INDEX 0x3A ++#define PACKET3_WAIT_REG_MEM 0x3C ++#define PACKET3_MEM_WRITE 0x3D ++#define PACKET3_SURFACE_SYNC 0x43 ++# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) ++# define PACKET3_CB1_DEST_BASE_ENA (1 << 7) ++# define PACKET3_CB2_DEST_BASE_ENA (1 << 8) ++# define PACKET3_CB3_DEST_BASE_ENA (1 << 9) ++# define PACKET3_CB4_DEST_BASE_ENA (1 << 10) ++# define PACKET3_CB5_DEST_BASE_ENA (1 << 11) ++# define PACKET3_CB6_DEST_BASE_ENA (1 << 12) ++# define PACKET3_CB7_DEST_BASE_ENA (1 << 13) ++# define PACKET3_DB_DEST_BASE_ENA (1 << 14) ++# define PACKET3_CB8_DEST_BASE_ENA (1 << 15) ++# define PACKET3_CB9_DEST_BASE_ENA (1 << 16) ++# define PACKET3_CB10_DEST_BASE_ENA (1 << 17) ++# define PACKET3_CB11_DEST_BASE_ENA (1 << 18) ++# define PACKET3_FULL_CACHE_ENA (1 << 20) ++# define PACKET3_TC_ACTION_ENA (1 << 23) ++# define PACKET3_CB_ACTION_ENA (1 << 25) ++# define PACKET3_DB_ACTION_ENA (1 << 26) ++# define PACKET3_SH_ACTION_ENA (1 << 27) ++# define PACKET3_SX_ACTION_ENA (1 << 28) ++#define PACKET3_ME_INITIALIZE 0x44 ++#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) ++#define PACKET3_COND_WRITE 0x45 ++#define PACKET3_EVENT_WRITE 0x46 ++#define PACKET3_EVENT_WRITE_EOP 0x47 ++#define PACKET3_EVENT_WRITE_EOS 0x48 ++#define PACKET3_PREAMBLE_CNTL 0x4A ++# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) ++# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) ++#define PACKET3_ALU_PS_CONST_BUFFER_COPY 0x4C ++#define PACKET3_ALU_VS_CONST_BUFFER_COPY 0x4D ++#define PACKET3_ALU_PS_CONST_UPDATE 0x4E ++#define PACKET3_ALU_VS_CONST_UPDATE 0x4F ++#define PACKET3_ONE_REG_WRITE 0x57 ++#define PACKET3_SET_CONFIG_REG 0x68 ++#define PACKET3_SET_CONFIG_REG_START 0x00008000 ++#define PACKET3_SET_CONFIG_REG_END 0x0000ac00 ++#define PACKET3_SET_CONTEXT_REG 0x69 ++#define PACKET3_SET_CONTEXT_REG_START 0x00028000 ++#define PACKET3_SET_CONTEXT_REG_END 0x00029000 ++#define PACKET3_SET_ALU_CONST 0x6A ++/* alu const buffers only; no reg file */ ++#define PACKET3_SET_BOOL_CONST 0x6B ++#define PACKET3_SET_BOOL_CONST_START 0x0003a500 ++#define PACKET3_SET_BOOL_CONST_END 0x0003a518 ++#define PACKET3_SET_LOOP_CONST 0x6C ++#define PACKET3_SET_LOOP_CONST_START 0x0003a200 ++#define PACKET3_SET_LOOP_CONST_END 0x0003a500 ++#define PACKET3_SET_RESOURCE 0x6D ++#define PACKET3_SET_RESOURCE_START 0x00030000 ++#define PACKET3_SET_RESOURCE_END 0x00038000 ++#define PACKET3_SET_SAMPLER 0x6E ++#define PACKET3_SET_SAMPLER_START 0x0003c000 ++#define PACKET3_SET_SAMPLER_END 0x0003c600 ++#define PACKET3_SET_CTL_CONST 0x6F ++#define PACKET3_SET_CTL_CONST_START 0x0003cff0 ++#define PACKET3_SET_CTL_CONST_END 0x0003ff0c ++#define PACKET3_SET_RESOURCE_OFFSET 0x70 ++#define PACKET3_SET_ALU_CONST_VS 0x71 ++#define PACKET3_SET_ALU_CONST_DI 0x72 ++#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 ++#define PACKET3_SET_RESOURCE_INDIRECT 0x74 ++#define PACKET3_SET_APPEND_CNT 0x75 ++ + #endif + +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index 9b3fad2..70e9fb0 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -47,6 +47,7 @@ + #define EVERGREEN_PFP_UCODE_SIZE 1120 + #define EVERGREEN_PM4_UCODE_SIZE 1376 + #define EVERGREEN_RLC_UCODE_SIZE 768 ++#define CAYMAN_RLC_UCODE_SIZE 1024 + + /* Firmware Names */ + MODULE_FIRMWARE("radeon/R600_pfp.bin"); +@@ -586,7 +587,7 @@ void r600_pm_misc(struct radeon_device *rdev) + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + if (voltage->voltage != rdev->pm.current_vddc) { +- radeon_atom_set_voltage(rdev, voltage->voltage); ++ radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG_DRIVER("Setting: v: %d\n", voltage->voltage); + } +@@ -2820,13 +2821,20 @@ static int r600_rlc_init(struct radeon_device *rdev) + WREG32(RLC_HB_CNTL, 0); + WREG32(RLC_HB_RPTR, 0); + WREG32(RLC_HB_WPTR, 0); +- WREG32(RLC_HB_WPTR_LSB_ADDR, 0); +- WREG32(RLC_HB_WPTR_MSB_ADDR, 0); ++ if (rdev->family <= CHIP_CAICOS) { ++ WREG32(RLC_HB_WPTR_LSB_ADDR, 0); ++ WREG32(RLC_HB_WPTR_MSB_ADDR, 0); ++ } + WREG32(RLC_MC_CNTL, 0); + WREG32(RLC_UCODE_CNTL, 0); + + fw_data = (const __be32 *)rdev->rlc_fw->data; +- if (rdev->family >= CHIP_CEDAR) { ++ if (rdev->family >= CHIP_CAYMAN) { ++ for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) { ++ WREG32(RLC_UCODE_ADDR, i); ++ WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); ++ } ++ } else if (rdev->family >= CHIP_CEDAR) { + for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) { + WREG32(RLC_UCODE_ADDR, i); + WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); +@@ -3227,7 +3235,7 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) + u32 wptr, tmp; + + if (rdev->wb.enabled) +- wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]; ++ wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); + else + wptr = RREG32(IH_RB_WPTR); + +diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c +index 153095f..0a0848f 100644 +--- a/drivers/gpu/drm/radeon/r600_cs.c ++++ b/drivers/gpu/drm/radeon/r600_cs.c +@@ -71,75 +71,167 @@ struct r600_cs_track { + u64 db_bo_mc; + }; + ++#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc } ++#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc } ++#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0 } ++#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc } ++#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0 } ++#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc } ++#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0 } ++#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16, vc } ++ ++struct gpu_formats { ++ unsigned blockwidth; ++ unsigned blockheight; ++ unsigned blocksize; ++ unsigned valid_color; ++}; ++ ++static const struct gpu_formats color_formats_table[] = { ++ /* 8 bit */ ++ FMT_8_BIT(V_038004_COLOR_8, 1), ++ FMT_8_BIT(V_038004_COLOR_4_4, 1), ++ FMT_8_BIT(V_038004_COLOR_3_3_2, 1), ++ FMT_8_BIT(V_038004_FMT_1, 0), ++ ++ /* 16-bit */ ++ FMT_16_BIT(V_038004_COLOR_16, 1), ++ FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1), ++ FMT_16_BIT(V_038004_COLOR_8_8, 1), ++ FMT_16_BIT(V_038004_COLOR_5_6_5, 1), ++ FMT_16_BIT(V_038004_COLOR_6_5_5, 1), ++ FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1), ++ FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1), ++ FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1), ++ ++ /* 24-bit */ ++ FMT_24_BIT(V_038004_FMT_8_8_8), ++ ++ /* 32-bit */ ++ FMT_32_BIT(V_038004_COLOR_32, 1), ++ FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1), ++ FMT_32_BIT(V_038004_COLOR_16_16, 1), ++ FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1), ++ FMT_32_BIT(V_038004_COLOR_8_24, 1), ++ FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1), ++ FMT_32_BIT(V_038004_COLOR_24_8, 1), ++ FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1), ++ FMT_32_BIT(V_038004_COLOR_10_11_11, 1), ++ FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1), ++ FMT_32_BIT(V_038004_COLOR_11_11_10, 1), ++ FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1), ++ FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1), ++ FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1), ++ FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1), ++ FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0), ++ FMT_32_BIT(V_038004_FMT_32_AS_8, 0), ++ FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0), ++ ++ /* 48-bit */ ++ FMT_48_BIT(V_038004_FMT_16_16_16), ++ FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT), ++ ++ /* 64-bit */ ++ FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1), ++ FMT_64_BIT(V_038004_COLOR_32_32, 1), ++ FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1), ++ FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1), ++ FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1), ++ ++ FMT_96_BIT(V_038004_FMT_32_32_32), ++ FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT), ++ ++ /* 128-bit */ ++ FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1), ++ FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1), ++ ++ [V_038004_FMT_GB_GR] = { 2, 1, 4, 0 }, ++ [V_038004_FMT_BG_RG] = { 2, 1, 4, 0 }, ++ ++ /* block compressed formats */ ++ [V_038004_FMT_BC1] = { 4, 4, 8, 0 }, ++ [V_038004_FMT_BC2] = { 4, 4, 16, 0 }, ++ [V_038004_FMT_BC3] = { 4, 4, 16, 0 }, ++ [V_038004_FMT_BC4] = { 4, 4, 8, 0 }, ++ [V_038004_FMT_BC5] = { 4, 4, 16, 0}, ++ ++}; ++ ++static inline bool fmt_is_valid_color(u32 format) ++{ ++ if (format >= ARRAY_SIZE(color_formats_table)) ++ return false; ++ ++ if (color_formats_table[format].valid_color) ++ return true; ++ ++ return false; ++} ++ ++static inline bool fmt_is_valid_texture(u32 format) ++{ ++ if (format >= ARRAY_SIZE(color_formats_table)) ++ return false; ++ ++ if (color_formats_table[format].blockwidth > 0) ++ return true; ++ ++ return false; ++} ++ ++static inline int fmt_get_blocksize(u32 format) ++{ ++ if (format >= ARRAY_SIZE(color_formats_table)) ++ return 0; ++ ++ return color_formats_table[format].blocksize; ++} ++ ++static inline int fmt_get_nblocksx(u32 format, u32 w) ++{ ++ unsigned bw; ++ ++ if (format >= ARRAY_SIZE(color_formats_table)) ++ return 0; ++ ++ bw = color_formats_table[format].blockwidth; ++ if (bw == 0) ++ return 0; ++ ++ return (w + bw - 1) / bw; ++} ++ ++static inline int fmt_get_nblocksy(u32 format, u32 h) ++{ ++ unsigned bh; ++ ++ if (format >= ARRAY_SIZE(color_formats_table)) ++ return 0; ++ ++ bh = color_formats_table[format].blockheight; ++ if (bh == 0) ++ return 0; ++ ++ return (h + bh - 1) / bh; ++} ++ + static inline int r600_bpe_from_format(u32 *bpe, u32 format) + { +- switch (format) { +- case V_038004_COLOR_8: +- case V_038004_COLOR_4_4: +- case V_038004_COLOR_3_3_2: +- case V_038004_FMT_1: +- *bpe = 1; +- break; +- case V_038004_COLOR_16: +- case V_038004_COLOR_16_FLOAT: +- case V_038004_COLOR_8_8: +- case V_038004_COLOR_5_6_5: +- case V_038004_COLOR_6_5_5: +- case V_038004_COLOR_1_5_5_5: +- case V_038004_COLOR_4_4_4_4: +- case V_038004_COLOR_5_5_5_1: +- *bpe = 2; +- break; +- case V_038004_FMT_8_8_8: +- *bpe = 3; +- break; +- case V_038004_COLOR_32: +- case V_038004_COLOR_32_FLOAT: +- case V_038004_COLOR_16_16: +- case V_038004_COLOR_16_16_FLOAT: +- case V_038004_COLOR_8_24: +- case V_038004_COLOR_8_24_FLOAT: +- case V_038004_COLOR_24_8: +- case V_038004_COLOR_24_8_FLOAT: +- case V_038004_COLOR_10_11_11: +- case V_038004_COLOR_10_11_11_FLOAT: +- case V_038004_COLOR_11_11_10: +- case V_038004_COLOR_11_11_10_FLOAT: +- case V_038004_COLOR_2_10_10_10: +- case V_038004_COLOR_8_8_8_8: +- case V_038004_COLOR_10_10_10_2: +- case V_038004_FMT_5_9_9_9_SHAREDEXP: +- case V_038004_FMT_32_AS_8: +- case V_038004_FMT_32_AS_8_8: +- *bpe = 4; +- break; +- case V_038004_COLOR_X24_8_32_FLOAT: +- case V_038004_COLOR_32_32: +- case V_038004_COLOR_32_32_FLOAT: +- case V_038004_COLOR_16_16_16_16: +- case V_038004_COLOR_16_16_16_16_FLOAT: +- *bpe = 8; +- break; +- case V_038004_FMT_16_16_16: +- case V_038004_FMT_16_16_16_FLOAT: +- *bpe = 6; +- break; +- case V_038004_FMT_32_32_32: +- case V_038004_FMT_32_32_32_FLOAT: +- *bpe = 12; +- break; +- case V_038004_COLOR_32_32_32_32: +- case V_038004_COLOR_32_32_32_32_FLOAT: +- *bpe = 16; +- break; +- case V_038004_FMT_GB_GR: +- case V_038004_FMT_BG_RG: +- case V_038004_COLOR_INVALID: +- default: +- *bpe = 16; +- return -EINVAL; +- } ++ unsigned res; ++ ++ if (format >= ARRAY_SIZE(color_formats_table)) ++ goto fail; ++ ++ res = color_formats_table[format].blocksize; ++ if (res == 0) ++ goto fail; ++ ++ *bpe = res; + return 0; ++ ++fail: ++ *bpe = 16; ++ return -EINVAL; + } + + struct array_mode_checker { +@@ -148,7 +240,7 @@ struct array_mode_checker { + u32 nbanks; + u32 npipes; + u32 nsamples; +- u32 bpe; ++ u32 blocksize; + }; + + /* returns alignment in pixels for pitch/height/depth and bytes for base */ +@@ -162,7 +254,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value + u32 tile_height = 8; + u32 macro_tile_width = values->nbanks; + u32 macro_tile_height = values->npipes; +- u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples; ++ u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples; + u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes; + + switch (values->array_mode) { +@@ -174,7 +266,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value + *base_align = 1; + break; + case ARRAY_LINEAR_ALIGNED: +- *pitch_align = max((u32)64, (u32)(values->group_size / values->bpe)); ++ *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize)); + *height_align = tile_height; + *depth_align = 1; + *base_align = values->group_size; +@@ -182,7 +274,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value + case ARRAY_1D_TILED_THIN1: + *pitch_align = max((u32)tile_width, + (u32)(values->group_size / +- (tile_height * values->bpe * values->nsamples))); ++ (tile_height * values->blocksize * values->nsamples))); + *height_align = tile_height; + *depth_align = 1; + *base_align = values->group_size; +@@ -190,12 +282,12 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value + case ARRAY_2D_TILED_THIN1: + *pitch_align = max((u32)macro_tile_width, + (u32)(((values->group_size / tile_height) / +- (values->bpe * values->nsamples)) * ++ (values->blocksize * values->nsamples)) * + values->nbanks)) * tile_width; + *height_align = macro_tile_height * tile_height; + *depth_align = 1; + *base_align = max(macro_tile_bytes, +- (*pitch_align) * values->bpe * (*height_align) * values->nsamples); ++ (*pitch_align) * values->blocksize * (*height_align) * values->nsamples); + break; + default: + return -EINVAL; +@@ -234,21 +326,22 @@ static void r600_cs_track_init(struct r600_cs_track *track) + static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + { + struct r600_cs_track *track = p->track; +- u32 bpe = 0, slice_tile_max, size, tmp; ++ u32 slice_tile_max, size, tmp; + u32 height, height_align, pitch, pitch_align, depth_align; + u64 base_offset, base_align; + struct array_mode_checker array_check; + volatile u32 *ib = p->ib->ptr; + unsigned array_mode; +- ++ u32 format; + if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { + dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); + return -EINVAL; + } + size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; +- if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) { ++ format = G_0280A0_FORMAT(track->cb_color_info[i]); ++ if (!fmt_is_valid_color(format)) { + dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", +- __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]), ++ __func__, __LINE__, format, + i, track->cb_color_info[i]); + return -EINVAL; + } +@@ -267,7 +360,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = track->nsamples; +- array_check.bpe = bpe; ++ array_check.blocksize = fmt_get_blocksize(format); + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, +@@ -311,7 +404,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) + } + + /* check offset */ +- tmp = height * pitch * bpe; ++ tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format); + if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { + if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { + /* the initial DDX does bad things with the CB size occasionally */ +@@ -436,7 +529,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = track->nsamples; +- array_check.bpe = bpe; ++ array_check.blocksize = bpe; + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, +@@ -1113,39 +1206,61 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx + return 0; + } + +-static inline unsigned minify(unsigned size, unsigned levels) ++static inline unsigned mip_minify(unsigned size, unsigned level) + { +- size = size >> levels; +- if (size < 1) +- size = 1; +- return size; ++ unsigned val; ++ ++ val = max(1U, size >> level); ++ if (level > 0) ++ val = roundup_pow_of_two(val); ++ return val; + } + +-static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels, +- unsigned w0, unsigned h0, unsigned d0, unsigned bpe, +- unsigned pitch_align, ++static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, ++ unsigned w0, unsigned h0, unsigned d0, unsigned format, ++ unsigned block_align, unsigned height_align, unsigned base_align, + unsigned *l0_size, unsigned *mipmap_size) + { +- unsigned offset, i, level, face; +- unsigned width, height, depth, rowstride, size; +- +- w0 = minify(w0, 0); +- h0 = minify(h0, 0); +- d0 = minify(d0, 0); ++ unsigned offset, i, level; ++ unsigned width, height, depth, size; ++ unsigned blocksize; ++ unsigned nbx, nby; ++ unsigned nlevels = llevel - blevel + 1; ++ ++ *l0_size = -1; ++ blocksize = fmt_get_blocksize(format); ++ ++ w0 = mip_minify(w0, 0); ++ h0 = mip_minify(h0, 0); ++ d0 = mip_minify(d0, 0); + for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) { +- width = minify(w0, i); +- height = minify(h0, i); +- depth = minify(d0, i); +- for(face = 0; face < nfaces; face++) { +- rowstride = ALIGN((width * bpe), pitch_align); +- size = height * rowstride * depth; +- offset += size; +- offset = (offset + 0x1f) & ~0x1f; +- } ++ width = mip_minify(w0, i); ++ nbx = fmt_get_nblocksx(format, width); ++ ++ nbx = round_up(nbx, block_align); ++ ++ height = mip_minify(h0, i); ++ nby = fmt_get_nblocksy(format, height); ++ nby = round_up(nby, height_align); ++ ++ depth = mip_minify(d0, i); ++ ++ size = nbx * nby * blocksize; ++ if (nfaces) ++ size *= nfaces; ++ else ++ size *= depth; ++ ++ if (i == 0) ++ *l0_size = size; ++ ++ if (i == 0 || i == 1) ++ offset = round_up(offset, base_align); ++ ++ offset += size; + } +- *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; + *mipmap_size = offset; +- if (!nlevels) ++ if (llevel == 0) + *mipmap_size = *l0_size; + if (!blevel) + *mipmap_size -= *l0_size; +@@ -1169,11 +1284,13 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i + u32 tiling_flags) + { + struct r600_cs_track *track = p->track; +- u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0; +- u32 word0, word1, l0_size, mipmap_size; ++ u32 nfaces, llevel, blevel, w0, h0, d0; ++ u32 word0, word1, l0_size, mipmap_size, word2, word3; + u32 height_align, pitch, pitch_align, depth_align; ++ u32 array, barray, larray; + u64 base_align; + struct array_mode_checker array_check; ++ u32 format; + + /* on legacy kernel we don't perform advanced check */ + if (p->rdev == NULL) +@@ -1199,19 +1316,25 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i + case V_038000_SQ_TEX_DIM_3D: + break; + case V_038000_SQ_TEX_DIM_CUBEMAP: +- nfaces = 6; ++ if (p->family >= CHIP_RV770) ++ nfaces = 8; ++ else ++ nfaces = 6; + break; + case V_038000_SQ_TEX_DIM_1D_ARRAY: + case V_038000_SQ_TEX_DIM_2D_ARRAY: ++ array = 1; ++ break; + case V_038000_SQ_TEX_DIM_2D_MSAA: + case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: + default: + dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); + return -EINVAL; + } +- if (r600_bpe_from_format(&bpe, G_038004_DATA_FORMAT(word1))) { ++ format = G_038004_DATA_FORMAT(word1); ++ if (!fmt_is_valid_texture(format)) { + dev_warn(p->dev, "%s:%d texture invalid format %d\n", +- __func__, __LINE__, G_038004_DATA_FORMAT(word1)); ++ __func__, __LINE__, format); + return -EINVAL; + } + +@@ -1222,7 +1345,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i + array_check.nbanks = track->nbanks; + array_check.npipes = track->npipes; + array_check.nsamples = 1; +- array_check.bpe = bpe; ++ array_check.blocksize = fmt_get_blocksize(format); + if (r600_get_array_mode_alignment(&array_check, + &pitch_align, &height_align, &depth_align, &base_align)) { + dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", +@@ -1248,25 +1371,34 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i + return -EINVAL; + } + ++ word2 = radeon_get_ib_value(p, idx + 2) << 8; ++ word3 = radeon_get_ib_value(p, idx + 3) << 8; ++ + word0 = radeon_get_ib_value(p, idx + 4); + word1 = radeon_get_ib_value(p, idx + 5); + blevel = G_038010_BASE_LEVEL(word0); +- nlevels = G_038014_LAST_LEVEL(word1); +- r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, +- (pitch_align * bpe), ++ llevel = G_038014_LAST_LEVEL(word1); ++ if (array == 1) { ++ barray = G_038014_BASE_ARRAY(word1); ++ larray = G_038014_LAST_ARRAY(word1); ++ ++ nfaces = larray - barray + 1; ++ } ++ r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, ++ pitch_align, height_align, base_align, + &l0_size, &mipmap_size); + /* using get ib will give us the offset into the texture bo */ +- word0 = radeon_get_ib_value(p, idx + 2) << 8; +- if ((l0_size + word0) > radeon_bo_size(texture)) { ++ if ((l0_size + word2) > radeon_bo_size(texture)) { + dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", +- w0, h0, bpe, word0, l0_size, radeon_bo_size(texture)); ++ w0, h0, format, word2, l0_size, radeon_bo_size(texture)); ++ dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align); + return -EINVAL; + } + /* using get ib will give us the offset into the mipmap bo */ +- word0 = radeon_get_ib_value(p, idx + 3) << 8; +- if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { ++ word3 = radeon_get_ib_value(p, idx + 3) << 8; ++ if ((mipmap_size + word3) > radeon_bo_size(mipmap)) { + /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", +- w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ ++ w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ + } + return 0; + } +@@ -1289,6 +1421,38 @@ static int r600_packet3_check(struct radeon_cs_parser *p, + idx_value = radeon_get_ib_value(p, idx); + + switch (pkt->opcode) { ++ case PACKET3_SET_PREDICATION: ++ { ++ int pred_op; ++ int tmp; ++ if (pkt->count != 1) { ++ DRM_ERROR("bad SET PREDICATION\n"); ++ return -EINVAL; ++ } ++ ++ tmp = radeon_get_ib_value(p, idx + 1); ++ pred_op = (tmp >> 16) & 0x7; ++ ++ /* for the clear predicate operation */ ++ if (pred_op == 0) ++ return 0; ++ ++ if (pred_op > 2) { ++ DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); ++ return -EINVAL; ++ } ++ ++ r = r600_cs_packet_next_reloc(p, &reloc); ++ if (r) { ++ DRM_ERROR("bad SET PREDICATION\n"); ++ return -EINVAL; ++ } ++ ++ ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); ++ ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); ++ } ++ break; ++ + case PACKET3_START_3D_CMDBUF: + if (p->family >= CHIP_RV770 || pkt->count) { + DRM_ERROR("bad START_3D\n"); +diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h +index 04bac0b..b2b944b 100644 +--- a/drivers/gpu/drm/radeon/r600d.h ++++ b/drivers/gpu/drm/radeon/r600d.h +@@ -1304,6 +1304,11 @@ + #define V_038004_FMT_16_16_16_FLOAT 0x0000002E + #define V_038004_FMT_32_32_32 0x0000002F + #define V_038004_FMT_32_32_32_FLOAT 0x00000030 ++#define V_038004_FMT_BC1 0x00000031 ++#define V_038004_FMT_BC2 0x00000032 ++#define V_038004_FMT_BC3 0x00000033 ++#define V_038004_FMT_BC4 0x00000034 ++#define V_038004_FMT_BC5 0x00000035 + #define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010 + #define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) + #define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) +diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +index 6b34294..27df931 100644 +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -177,7 +177,7 @@ void radeon_pm_suspend(struct radeon_device *rdev); + void radeon_pm_resume(struct radeon_device *rdev); + void radeon_combios_get_power_modes(struct radeon_device *rdev); + void radeon_atombios_get_power_modes(struct radeon_device *rdev); +-void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level); ++void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); + void rs690_pm_info(struct radeon_device *rdev); + extern int rv6xx_get_temp(struct radeon_device *rdev); + extern int rv770_get_temp(struct radeon_device *rdev); +@@ -651,6 +651,8 @@ struct radeon_wb { + + #define RADEON_WB_SCRATCH_OFFSET 0 + #define RADEON_WB_CP_RPTR_OFFSET 1024 ++#define RADEON_WB_CP1_RPTR_OFFSET 1280 ++#define RADEON_WB_CP2_RPTR_OFFSET 1536 + #define R600_WB_IH_WPTR_OFFSET 2048 + #define R600_WB_EVENT_OFFSET 3072 + +@@ -753,7 +755,9 @@ struct radeon_voltage { + u8 vddci_id; /* index into vddci voltage table */ + bool vddci_enabled; + /* r6xx+ sw */ +- u32 voltage; ++ u16 voltage; ++ /* evergreen+ vddci */ ++ u16 vddci; + }; + + /* clock mode flags */ +@@ -821,10 +825,12 @@ struct radeon_pm { + int default_power_state_index; + u32 current_sclk; + u32 current_mclk; +- u32 current_vddc; ++ u16 current_vddc; ++ u16 current_vddci; + u32 default_sclk; + u32 default_mclk; +- u32 default_vddc; ++ u16 default_vddc; ++ u16 default_vddci; + struct radeon_i2c_chan *i2c_bus; + /* selected pm method */ + enum radeon_pm_method pm_method; +@@ -1037,12 +1043,52 @@ struct evergreen_asic { + struct r100_gpu_lockup lockup; + }; + ++struct cayman_asic { ++ unsigned max_shader_engines; ++ unsigned max_pipes_per_simd; ++ unsigned max_tile_pipes; ++ unsigned max_simds_per_se; ++ unsigned max_backends_per_se; ++ unsigned max_texture_channel_caches; ++ unsigned max_gprs; ++ unsigned max_threads; ++ unsigned max_gs_threads; ++ unsigned max_stack_entries; ++ unsigned sx_num_of_sets; ++ unsigned sx_max_export_size; ++ unsigned sx_max_export_pos_size; ++ unsigned sx_max_export_smx_size; ++ unsigned max_hw_contexts; ++ unsigned sq_num_cf_insts; ++ unsigned sc_prim_fifo_size; ++ unsigned sc_hiz_tile_fifo_size; ++ unsigned sc_earlyz_tile_fifo_size; ++ ++ unsigned num_shader_engines; ++ unsigned num_shader_pipes_per_simd; ++ unsigned num_tile_pipes; ++ unsigned num_simds_per_se; ++ unsigned num_backends_per_se; ++ unsigned backend_disable_mask_per_asic; ++ unsigned backend_map; ++ unsigned num_texture_channel_caches; ++ unsigned mem_max_burst_length_bytes; ++ unsigned mem_row_size_in_kb; ++ unsigned shader_engine_tile_size; ++ unsigned num_gpus; ++ unsigned multi_gpu_tile_size; ++ ++ unsigned tile_config; ++ struct r100_gpu_lockup lockup; ++}; ++ + union radeon_asic_config { + struct r300_asic r300; + struct r100_asic r100; + struct r600_asic r600; + struct rv770_asic rv770; + struct evergreen_asic evergreen; ++ struct cayman_asic cayman; + }; + + /* +@@ -1133,6 +1179,9 @@ struct radeon_device { + struct radeon_mman mman; + struct radeon_fence_driver fence_drv; + struct radeon_cp cp; ++ /* cayman compute rings */ ++ struct radeon_cp cp1; ++ struct radeon_cp cp2; + struct radeon_ib_pool ib_pool; + struct radeon_irq irq; + struct radeon_asic *asic; +@@ -1504,7 +1553,7 @@ extern int evergreen_blit_init(struct radeon_device *rdev); + extern void evergreen_blit_fini(struct radeon_device *rdev); + + extern int ni_init_microcode(struct radeon_device *rdev); +-extern int btc_mc_load_microcode(struct radeon_device *rdev); ++extern int ni_mc_load_microcode(struct radeon_device *rdev); + + /* radeon_acpi.c */ + #if defined(CONFIG_ACPI) +diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +index 793c5e6..ca57619 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -94,7 +94,7 @@ static void radeon_register_accessor_init(struct radeon_device *rdev) + rdev->mc_rreg = &rs600_mc_rreg; + rdev->mc_wreg = &rs600_mc_wreg; + } +- if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_HEMLOCK)) { ++ if (rdev->family >= CHIP_R600) { + rdev->pciep_rreg = &r600_pciep_rreg; + rdev->pciep_wreg = &r600_pciep_wreg; + } +@@ -885,6 +885,52 @@ static struct radeon_asic btc_asic = { + .post_page_flip = &evergreen_post_page_flip, + }; + ++static struct radeon_asic cayman_asic = { ++ .init = &cayman_init, ++ .fini = &cayman_fini, ++ .suspend = &cayman_suspend, ++ .resume = &cayman_resume, ++ .cp_commit = &r600_cp_commit, ++ .gpu_is_lockup = &cayman_gpu_is_lockup, ++ .asic_reset = &cayman_asic_reset, ++ .vga_set_state = &r600_vga_set_state, ++ .gart_tlb_flush = &cayman_pcie_gart_tlb_flush, ++ .gart_set_page = &rs600_gart_set_page, ++ .ring_test = &r600_ring_test, ++ .ring_ib_execute = &evergreen_ring_ib_execute, ++ .irq_set = &evergreen_irq_set, ++ .irq_process = &evergreen_irq_process, ++ .get_vblank_counter = &evergreen_get_vblank_counter, ++ .fence_ring_emit = &r600_fence_ring_emit, ++ .cs_parse = &evergreen_cs_parse, ++ .copy_blit = NULL, ++ .copy_dma = NULL, ++ .copy = NULL, ++ .get_engine_clock = &radeon_atom_get_engine_clock, ++ .set_engine_clock = &radeon_atom_set_engine_clock, ++ .get_memory_clock = &radeon_atom_get_memory_clock, ++ .set_memory_clock = &radeon_atom_set_memory_clock, ++ .get_pcie_lanes = NULL, ++ .set_pcie_lanes = NULL, ++ .set_clock_gating = NULL, ++ .set_surface_reg = r600_set_surface_reg, ++ .clear_surface_reg = r600_clear_surface_reg, ++ .bandwidth_update = &evergreen_bandwidth_update, ++ .hpd_init = &evergreen_hpd_init, ++ .hpd_fini = &evergreen_hpd_fini, ++ .hpd_sense = &evergreen_hpd_sense, ++ .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .gui_idle = &r600_gui_idle, ++ .pm_misc = &evergreen_pm_misc, ++ .pm_prepare = &evergreen_pm_prepare, ++ .pm_finish = &evergreen_pm_finish, ++ .pm_init_profile = &r600_pm_init_profile, ++ .pm_get_dynpm_state = &r600_pm_get_dynpm_state, ++ .pre_page_flip = &evergreen_pre_page_flip, ++ .page_flip = &evergreen_page_flip, ++ .post_page_flip = &evergreen_post_page_flip, ++}; ++ + int radeon_asic_init(struct radeon_device *rdev) + { + radeon_register_accessor_init(rdev); +@@ -977,6 +1023,9 @@ int radeon_asic_init(struct radeon_device *rdev) + case CHIP_CAICOS: + rdev->asic = &btc_asic; + break; ++ case CHIP_CAYMAN: ++ rdev->asic = &cayman_asic; ++ break; + default: + /* FIXME: not supported yet */ + return -EINVAL; +diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h +index c59bd98..82c4bc2 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.h ++++ b/drivers/gpu/drm/radeon/radeon_asic.h +@@ -375,4 +375,15 @@ extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); + extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); + extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); + ++/* ++ * cayman ++ */ ++void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev); ++int cayman_init(struct radeon_device *rdev); ++void cayman_fini(struct radeon_device *rdev); ++int cayman_suspend(struct radeon_device *rdev); ++int cayman_resume(struct radeon_device *rdev); ++bool cayman_gpu_is_lockup(struct radeon_device *rdev); ++int cayman_asic_reset(struct radeon_device *rdev); ++ + #endif +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index 99768d9..f116516 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -1599,9 +1599,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct + memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], + fake_edid_record->ucFakeEDIDLength); + +- if (drm_edid_is_valid(edid)) ++ if (drm_edid_is_valid(edid)) { + rdev->mode_info.bios_hardcoded_edid = edid; +- else ++ rdev->mode_info.bios_hardcoded_edid_size = edid_size; ++ } else + kfree(edid); + } + } +@@ -2176,24 +2177,27 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r + } + } + +-static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev) ++static void radeon_atombios_get_default_voltages(struct radeon_device *rdev, ++ u16 *vddc, u16 *vddci) + { + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + u8 frev, crev; + u16 data_offset; + union firmware_info *firmware_info; +- u16 vddc = 0; ++ ++ *vddc = 0; ++ *vddci = 0; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + firmware_info = + (union firmware_info *)(mode_info->atom_context->bios + + data_offset); +- vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); ++ *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); ++ if ((frev == 2) && (crev >= 2)) ++ *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); + } +- +- return vddc; + } + + static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, +@@ -2203,7 +2207,9 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde + int j; + u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); + u32 misc2 = le16_to_cpu(non_clock_info->usClassification); +- u16 vddc = radeon_atombios_get_default_vddc(rdev); ++ u16 vddc, vddci; ++ ++ radeon_atombios_get_default_voltages(rdev, &vddc, &vddci); + + rdev->pm.power_state[state_index].misc = misc; + rdev->pm.power_state[state_index].misc2 = misc2; +@@ -2244,6 +2250,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde + rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; + rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; + rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; ++ rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; + } else { + /* patch the table values with the default slck/mclk from firmware info */ + for (j = 0; j < mode_index; j++) { +@@ -2286,6 +2293,8 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, + VOLTAGE_SW; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = + le16_to_cpu(clock_info->evergreen.usVDDC); ++ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = ++ le16_to_cpu(clock_info->evergreen.usVDDCI); + } else { + sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); + sclk |= clock_info->r600.ucEngineClockHigh << 16; +@@ -2577,25 +2586,25 @@ union set_voltage { + struct _SET_VOLTAGE_PARAMETERS_V2 v2; + }; + +-void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level) ++void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type) + { + union set_voltage args; + int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); +- u8 frev, crev, volt_index = level; ++ u8 frev, crev, volt_index = voltage_level; + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + + switch (crev) { + case 1: +- args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC; ++ args.v1.ucVoltageType = voltage_type; + args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE; + args.v1.ucVoltageIndex = volt_index; + break; + case 2: +- args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC; ++ args.v2.ucVoltageType = voltage_type; + args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE; +- args.v2.usVoltageLevel = cpu_to_le16(level); ++ args.v2.usVoltageLevel = cpu_to_le16(voltage_level); + break; + default: + DRM_ERROR("Unknown table version %d, %d\n", frev, crev); +diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c +index cf602e2..8caf546 100644 +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -2079,6 +2079,19 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); ++ /* TV - TV DAC */ ++ ddc_i2c.valid = false; ++ hpd.hpd = RADEON_HPD_NONE; ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_TV1_SUPPORT, ++ 2), ++ ATOM_DEVICE_TV1_SUPPORT); ++ radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, ++ DRM_MODE_CONNECTOR_SVIDEO, ++ &ddc_i2c, ++ CONNECTOR_OBJECT_ID_SVIDEO, ++ &hpd); + break; + default: + DRM_INFO("Connector table: %d (invalid)\n", +diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c +index d83338b..a186673 100644 +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -998,7 +998,16 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, + (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || + (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) + return MODE_OK; +- else ++ else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) { ++ if (ASIC_IS_DCE3(rdev)) { ++ /* HDMI 1.3+ supports max clock of 340 Mhz */ ++ if (mode->clock > 340000) ++ return MODE_CLOCK_HIGH; ++ else ++ return MODE_OK; ++ } else ++ return MODE_CLOCK_HIGH; ++ } else + return MODE_CLOCK_HIGH; + } + return MODE_OK; +diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c +index 4954e2d..207d43f 100644 +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -85,6 +85,7 @@ static const char radeon_family_name[][16] = { + "BARTS", + "TURKS", + "CAICOS", ++ "CAYMAN", + "LAST", + }; + +diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c +index 275b26a..0444911 100644 +--- a/drivers/gpu/drm/radeon/radeon_drv.c ++++ b/drivers/gpu/drm/radeon/radeon_drv.c +@@ -49,9 +49,10 @@ + * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) + * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs + * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query ++ * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query + */ + #define KMS_DRIVER_MAJOR 2 +-#define KMS_DRIVER_MINOR 8 ++#define KMS_DRIVER_MINOR 9 + #define KMS_DRIVER_PATCHLEVEL 0 + int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); + int radeon_driver_unload_kms(struct drm_device *dev); +diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h +index 1ca55eb..6f1d9e5 100644 +--- a/drivers/gpu/drm/radeon/radeon_family.h ++++ b/drivers/gpu/drm/radeon/radeon_family.h +@@ -84,6 +84,7 @@ enum radeon_family { + CHIP_BARTS, + CHIP_TURKS, + CHIP_CAICOS, ++ CHIP_CAYMAN, + CHIP_LAST, + }; + +diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c +index 8387d32..d36fe3f 100644 +--- a/drivers/gpu/drm/radeon/radeon_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_kms.c +@@ -169,7 +169,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + value = rdev->accel_working; + break; + case RADEON_INFO_TILING_CONFIG: +- if (rdev->family >= CHIP_CEDAR) ++ if (rdev->family >= CHIP_CAYMAN) ++ value = rdev->config.cayman.tile_config; ++ else if (rdev->family >= CHIP_CEDAR) + value = rdev->config.evergreen.tile_config; + else if (rdev->family >= CHIP_RV770) + value = rdev->config.rv770.tile_config; +@@ -205,6 +207,36 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) + /* return clock value in KHz */ + value = rdev->clock.spll.reference_freq * 10; + break; ++ case RADEON_INFO_NUM_BACKENDS: ++ if (rdev->family >= CHIP_CAYMAN) ++ value = rdev->config.cayman.max_backends_per_se * ++ rdev->config.cayman.max_shader_engines; ++ else if (rdev->family >= CHIP_CEDAR) ++ value = rdev->config.evergreen.max_backends; ++ else if (rdev->family >= CHIP_RV770) ++ value = rdev->config.rv770.max_backends; ++ else if (rdev->family >= CHIP_R600) ++ value = rdev->config.r600.max_backends; ++ else { ++ return -EINVAL; ++ } ++ break; ++ case RADEON_INFO_NUM_TILE_PIPES: ++ if (rdev->family >= CHIP_CAYMAN) ++ value = rdev->config.cayman.max_tile_pipes; ++ else if (rdev->family >= CHIP_CEDAR) ++ value = rdev->config.evergreen.max_tile_pipes; ++ else if (rdev->family >= CHIP_RV770) ++ value = rdev->config.rv770.max_tile_pipes; ++ else if (rdev->family >= CHIP_R600) ++ value = rdev->config.r600.max_tile_pipes; ++ else { ++ return -EINVAL; ++ } ++ break; ++ case RADEON_INFO_FUSION_GART_WORKING: ++ value = 1; ++ break; + default: + DRM_DEBUG_KMS("Invalid request %d\n", info->request); + return -EINVAL; +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index 2aed03b..320ddc3 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -23,6 +23,7 @@ + #include "drmP.h" + #include "radeon.h" + #include "avivod.h" ++#include "atom.h" + #ifdef CONFIG_ACPI + #include + #endif +@@ -533,7 +534,11 @@ void radeon_pm_resume(struct radeon_device *rdev) + /* set up the default clocks if the MC ucode is loaded */ + if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if (rdev->pm.default_vddc) +- radeon_atom_set_voltage(rdev, rdev->pm.default_vddc); ++ radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, ++ SET_VOLTAGE_TYPE_ASIC_VDDC); ++ if (rdev->pm.default_vddci) ++ radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, ++ SET_VOLTAGE_TYPE_ASIC_VDDCI); + if (rdev->pm.default_sclk) + radeon_set_engine_clock(rdev, rdev->pm.default_sclk); + if (rdev->pm.default_mclk) +@@ -546,6 +551,7 @@ void radeon_pm_resume(struct radeon_device *rdev) + rdev->pm.current_sclk = rdev->pm.default_sclk; + rdev->pm.current_mclk = rdev->pm.default_mclk; + rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; ++ rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci; + if (rdev->pm.pm_method == PM_METHOD_DYNPM + && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { + rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; +@@ -583,7 +589,8 @@ int radeon_pm_init(struct radeon_device *rdev) + /* set up the default clocks if the MC ucode is loaded */ + if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if (rdev->pm.default_vddc) +- radeon_atom_set_voltage(rdev, rdev->pm.default_vddc); ++ radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, ++ SET_VOLTAGE_TYPE_ASIC_VDDC); + if (rdev->pm.default_sclk) + radeon_set_engine_clock(rdev, rdev->pm.default_sclk); + if (rdev->pm.default_mclk) +diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman +new file mode 100644 +index 0000000..6334f8a +--- /dev/null ++++ b/drivers/gpu/drm/radeon/reg_srcs/cayman +@@ -0,0 +1,619 @@ ++cayman 0x9400 ++0x0000802C GRBM_GFX_INDEX ++0x000088B0 VGT_VTX_VECT_EJECT_REG ++0x000088C4 VGT_CACHE_INVALIDATION ++0x000088D4 VGT_GS_VERTEX_REUSE ++0x00008958 VGT_PRIMITIVE_TYPE ++0x0000895C VGT_INDEX_TYPE ++0x00008970 VGT_NUM_INDICES ++0x00008974 VGT_NUM_INSTANCES ++0x00008990 VGT_COMPUTE_DIM_X ++0x00008994 VGT_COMPUTE_DIM_Y ++0x00008998 VGT_COMPUTE_DIM_Z ++0x0000899C VGT_COMPUTE_START_X ++0x000089A0 VGT_COMPUTE_START_Y ++0x000089A4 VGT_COMPUTE_START_Z ++0x000089A8 VGT_COMPUTE_INDEX ++0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE ++0x000089B0 VGT_HS_OFFCHIP_PARAM ++0x00008A14 PA_CL_ENHANCE ++0x00008A60 PA_SC_LINE_STIPPLE_VALUE ++0x00008B10 PA_SC_LINE_STIPPLE_STATE ++0x00008BF0 PA_SC_ENHANCE ++0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ ++0x00008D94 SQ_DYN_GPR_SIMD_LOCK_EN ++0x00008C00 SQ_CONFIG ++0x00008C04 SQ_GPR_RESOURCE_MGMT_1 ++0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1 ++0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2 ++0x00008DF8 SQ_CONST_MEM_BASE ++0x00008E20 SQ_STATIC_THREAD_MGMT_1 ++0x00008E24 SQ_STATIC_THREAD_MGMT_2 ++0x00008E28 SQ_STATIC_THREAD_MGMT_3 ++0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS ++0x00009100 SPI_CONFIG_CNTL ++0x0000913C SPI_CONFIG_CNTL_1 ++0x00009830 DB_DEBUG ++0x00009834 DB_DEBUG2 ++0x00009838 DB_DEBUG3 ++0x0000983C DB_DEBUG4 ++0x00009854 DB_WATERMARKS ++0x0000A400 TD_PS_BORDER_COLOR_INDEX ++0x0000A404 TD_PS_BORDER_COLOR_RED ++0x0000A408 TD_PS_BORDER_COLOR_GREEN ++0x0000A40C TD_PS_BORDER_COLOR_BLUE ++0x0000A410 TD_PS_BORDER_COLOR_ALPHA ++0x0000A414 TD_VS_BORDER_COLOR_INDEX ++0x0000A418 TD_VS_BORDER_COLOR_RED ++0x0000A41C TD_VS_BORDER_COLOR_GREEN ++0x0000A420 TD_VS_BORDER_COLOR_BLUE ++0x0000A424 TD_VS_BORDER_COLOR_ALPHA ++0x0000A428 TD_GS_BORDER_COLOR_INDEX ++0x0000A42C TD_GS_BORDER_COLOR_RED ++0x0000A430 TD_GS_BORDER_COLOR_GREEN ++0x0000A434 TD_GS_BORDER_COLOR_BLUE ++0x0000A438 TD_GS_BORDER_COLOR_ALPHA ++0x0000A43C TD_HS_BORDER_COLOR_INDEX ++0x0000A440 TD_HS_BORDER_COLOR_RED ++0x0000A444 TD_HS_BORDER_COLOR_GREEN ++0x0000A448 TD_HS_BORDER_COLOR_BLUE ++0x0000A44C TD_HS_BORDER_COLOR_ALPHA ++0x0000A450 TD_LS_BORDER_COLOR_INDEX ++0x0000A454 TD_LS_BORDER_COLOR_RED ++0x0000A458 TD_LS_BORDER_COLOR_GREEN ++0x0000A45C TD_LS_BORDER_COLOR_BLUE ++0x0000A460 TD_LS_BORDER_COLOR_ALPHA ++0x0000A464 TD_CS_BORDER_COLOR_INDEX ++0x0000A468 TD_CS_BORDER_COLOR_RED ++0x0000A46C TD_CS_BORDER_COLOR_GREEN ++0x0000A470 TD_CS_BORDER_COLOR_BLUE ++0x0000A474 TD_CS_BORDER_COLOR_ALPHA ++0x00028000 DB_RENDER_CONTROL ++0x00028004 DB_COUNT_CONTROL ++0x0002800C DB_RENDER_OVERRIDE ++0x00028010 DB_RENDER_OVERRIDE2 ++0x00028028 DB_STENCIL_CLEAR ++0x0002802C DB_DEPTH_CLEAR ++0x00028030 PA_SC_SCREEN_SCISSOR_TL ++0x00028034 PA_SC_SCREEN_SCISSOR_BR ++0x0002805C DB_DEPTH_SLICE ++0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 ++0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 ++0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 ++0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3 ++0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4 ++0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5 ++0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6 ++0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7 ++0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8 ++0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9 ++0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10 ++0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11 ++0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12 ++0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13 ++0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14 ++0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15 ++0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0 ++0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1 ++0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2 ++0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3 ++0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4 ++0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5 ++0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6 ++0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7 ++0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8 ++0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9 ++0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10 ++0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11 ++0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12 ++0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13 ++0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14 ++0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15 ++0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0 ++0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1 ++0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2 ++0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3 ++0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4 ++0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5 ++0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6 ++0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7 ++0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8 ++0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9 ++0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10 ++0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11 ++0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12 ++0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13 ++0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14 ++0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15 ++0x00028200 PA_SC_WINDOW_OFFSET ++0x00028204 PA_SC_WINDOW_SCISSOR_TL ++0x00028208 PA_SC_WINDOW_SCISSOR_BR ++0x0002820C PA_SC_CLIPRECT_RULE ++0x00028210 PA_SC_CLIPRECT_0_TL ++0x00028214 PA_SC_CLIPRECT_0_BR ++0x00028218 PA_SC_CLIPRECT_1_TL ++0x0002821C PA_SC_CLIPRECT_1_BR ++0x00028220 PA_SC_CLIPRECT_2_TL ++0x00028224 PA_SC_CLIPRECT_2_BR ++0x00028228 PA_SC_CLIPRECT_3_TL ++0x0002822C PA_SC_CLIPRECT_3_BR ++0x00028230 PA_SC_EDGERULE ++0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET ++0x00028240 PA_SC_GENERIC_SCISSOR_TL ++0x00028244 PA_SC_GENERIC_SCISSOR_BR ++0x00028250 PA_SC_VPORT_SCISSOR_0_TL ++0x00028254 PA_SC_VPORT_SCISSOR_0_BR ++0x00028258 PA_SC_VPORT_SCISSOR_1_TL ++0x0002825C PA_SC_VPORT_SCISSOR_1_BR ++0x00028260 PA_SC_VPORT_SCISSOR_2_TL ++0x00028264 PA_SC_VPORT_SCISSOR_2_BR ++0x00028268 PA_SC_VPORT_SCISSOR_3_TL ++0x0002826C PA_SC_VPORT_SCISSOR_3_BR ++0x00028270 PA_SC_VPORT_SCISSOR_4_TL ++0x00028274 PA_SC_VPORT_SCISSOR_4_BR ++0x00028278 PA_SC_VPORT_SCISSOR_5_TL ++0x0002827C PA_SC_VPORT_SCISSOR_5_BR ++0x00028280 PA_SC_VPORT_SCISSOR_6_TL ++0x00028284 PA_SC_VPORT_SCISSOR_6_BR ++0x00028288 PA_SC_VPORT_SCISSOR_7_TL ++0x0002828C PA_SC_VPORT_SCISSOR_7_BR ++0x00028290 PA_SC_VPORT_SCISSOR_8_TL ++0x00028294 PA_SC_VPORT_SCISSOR_8_BR ++0x00028298 PA_SC_VPORT_SCISSOR_9_TL ++0x0002829C PA_SC_VPORT_SCISSOR_9_BR ++0x000282A0 PA_SC_VPORT_SCISSOR_10_TL ++0x000282A4 PA_SC_VPORT_SCISSOR_10_BR ++0x000282A8 PA_SC_VPORT_SCISSOR_11_TL ++0x000282AC PA_SC_VPORT_SCISSOR_11_BR ++0x000282B0 PA_SC_VPORT_SCISSOR_12_TL ++0x000282B4 PA_SC_VPORT_SCISSOR_12_BR ++0x000282B8 PA_SC_VPORT_SCISSOR_13_TL ++0x000282BC PA_SC_VPORT_SCISSOR_13_BR ++0x000282C0 PA_SC_VPORT_SCISSOR_14_TL ++0x000282C4 PA_SC_VPORT_SCISSOR_14_BR ++0x000282C8 PA_SC_VPORT_SCISSOR_15_TL ++0x000282CC PA_SC_VPORT_SCISSOR_15_BR ++0x000282D0 PA_SC_VPORT_ZMIN_0 ++0x000282D4 PA_SC_VPORT_ZMAX_0 ++0x000282D8 PA_SC_VPORT_ZMIN_1 ++0x000282DC PA_SC_VPORT_ZMAX_1 ++0x000282E0 PA_SC_VPORT_ZMIN_2 ++0x000282E4 PA_SC_VPORT_ZMAX_2 ++0x000282E8 PA_SC_VPORT_ZMIN_3 ++0x000282EC PA_SC_VPORT_ZMAX_3 ++0x000282F0 PA_SC_VPORT_ZMIN_4 ++0x000282F4 PA_SC_VPORT_ZMAX_4 ++0x000282F8 PA_SC_VPORT_ZMIN_5 ++0x000282FC PA_SC_VPORT_ZMAX_5 ++0x00028300 PA_SC_VPORT_ZMIN_6 ++0x00028304 PA_SC_VPORT_ZMAX_6 ++0x00028308 PA_SC_VPORT_ZMIN_7 ++0x0002830C PA_SC_VPORT_ZMAX_7 ++0x00028310 PA_SC_VPORT_ZMIN_8 ++0x00028314 PA_SC_VPORT_ZMAX_8 ++0x00028318 PA_SC_VPORT_ZMIN_9 ++0x0002831C PA_SC_VPORT_ZMAX_9 ++0x00028320 PA_SC_VPORT_ZMIN_10 ++0x00028324 PA_SC_VPORT_ZMAX_10 ++0x00028328 PA_SC_VPORT_ZMIN_11 ++0x0002832C PA_SC_VPORT_ZMAX_11 ++0x00028330 PA_SC_VPORT_ZMIN_12 ++0x00028334 PA_SC_VPORT_ZMAX_12 ++0x00028338 PA_SC_VPORT_ZMIN_13 ++0x0002833C PA_SC_VPORT_ZMAX_13 ++0x00028340 PA_SC_VPORT_ZMIN_14 ++0x00028344 PA_SC_VPORT_ZMAX_14 ++0x00028348 PA_SC_VPORT_ZMIN_15 ++0x0002834C PA_SC_VPORT_ZMAX_15 ++0x00028350 SX_MISC ++0x00028354 SX_SURFACE_SYNC ++0x00028380 SQ_VTX_SEMANTIC_0 ++0x00028384 SQ_VTX_SEMANTIC_1 ++0x00028388 SQ_VTX_SEMANTIC_2 ++0x0002838C SQ_VTX_SEMANTIC_3 ++0x00028390 SQ_VTX_SEMANTIC_4 ++0x00028394 SQ_VTX_SEMANTIC_5 ++0x00028398 SQ_VTX_SEMANTIC_6 ++0x0002839C SQ_VTX_SEMANTIC_7 ++0x000283A0 SQ_VTX_SEMANTIC_8 ++0x000283A4 SQ_VTX_SEMANTIC_9 ++0x000283A8 SQ_VTX_SEMANTIC_10 ++0x000283AC SQ_VTX_SEMANTIC_11 ++0x000283B0 SQ_VTX_SEMANTIC_12 ++0x000283B4 SQ_VTX_SEMANTIC_13 ++0x000283B8 SQ_VTX_SEMANTIC_14 ++0x000283BC SQ_VTX_SEMANTIC_15 ++0x000283C0 SQ_VTX_SEMANTIC_16 ++0x000283C4 SQ_VTX_SEMANTIC_17 ++0x000283C8 SQ_VTX_SEMANTIC_18 ++0x000283CC SQ_VTX_SEMANTIC_19 ++0x000283D0 SQ_VTX_SEMANTIC_20 ++0x000283D4 SQ_VTX_SEMANTIC_21 ++0x000283D8 SQ_VTX_SEMANTIC_22 ++0x000283DC SQ_VTX_SEMANTIC_23 ++0x000283E0 SQ_VTX_SEMANTIC_24 ++0x000283E4 SQ_VTX_SEMANTIC_25 ++0x000283E8 SQ_VTX_SEMANTIC_26 ++0x000283EC SQ_VTX_SEMANTIC_27 ++0x000283F0 SQ_VTX_SEMANTIC_28 ++0x000283F4 SQ_VTX_SEMANTIC_29 ++0x000283F8 SQ_VTX_SEMANTIC_30 ++0x000283FC SQ_VTX_SEMANTIC_31 ++0x00028400 VGT_MAX_VTX_INDX ++0x00028404 VGT_MIN_VTX_INDX ++0x00028408 VGT_INDX_OFFSET ++0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX ++0x00028410 SX_ALPHA_TEST_CONTROL ++0x00028414 CB_BLEND_RED ++0x00028418 CB_BLEND_GREEN ++0x0002841C CB_BLEND_BLUE ++0x00028420 CB_BLEND_ALPHA ++0x00028430 DB_STENCILREFMASK ++0x00028434 DB_STENCILREFMASK_BF ++0x00028438 SX_ALPHA_REF ++0x0002843C PA_CL_VPORT_XSCALE_0 ++0x00028440 PA_CL_VPORT_XOFFSET_0 ++0x00028444 PA_CL_VPORT_YSCALE_0 ++0x00028448 PA_CL_VPORT_YOFFSET_0 ++0x0002844C PA_CL_VPORT_ZSCALE_0 ++0x00028450 PA_CL_VPORT_ZOFFSET_0 ++0x00028454 PA_CL_VPORT_XSCALE_1 ++0x00028458 PA_CL_VPORT_XOFFSET_1 ++0x0002845C PA_CL_VPORT_YSCALE_1 ++0x00028460 PA_CL_VPORT_YOFFSET_1 ++0x00028464 PA_CL_VPORT_ZSCALE_1 ++0x00028468 PA_CL_VPORT_ZOFFSET_1 ++0x0002846C PA_CL_VPORT_XSCALE_2 ++0x00028470 PA_CL_VPORT_XOFFSET_2 ++0x00028474 PA_CL_VPORT_YSCALE_2 ++0x00028478 PA_CL_VPORT_YOFFSET_2 ++0x0002847C PA_CL_VPORT_ZSCALE_2 ++0x00028480 PA_CL_VPORT_ZOFFSET_2 ++0x00028484 PA_CL_VPORT_XSCALE_3 ++0x00028488 PA_CL_VPORT_XOFFSET_3 ++0x0002848C PA_CL_VPORT_YSCALE_3 ++0x00028490 PA_CL_VPORT_YOFFSET_3 ++0x00028494 PA_CL_VPORT_ZSCALE_3 ++0x00028498 PA_CL_VPORT_ZOFFSET_3 ++0x0002849C PA_CL_VPORT_XSCALE_4 ++0x000284A0 PA_CL_VPORT_XOFFSET_4 ++0x000284A4 PA_CL_VPORT_YSCALE_4 ++0x000284A8 PA_CL_VPORT_YOFFSET_4 ++0x000284AC PA_CL_VPORT_ZSCALE_4 ++0x000284B0 PA_CL_VPORT_ZOFFSET_4 ++0x000284B4 PA_CL_VPORT_XSCALE_5 ++0x000284B8 PA_CL_VPORT_XOFFSET_5 ++0x000284BC PA_CL_VPORT_YSCALE_5 ++0x000284C0 PA_CL_VPORT_YOFFSET_5 ++0x000284C4 PA_CL_VPORT_ZSCALE_5 ++0x000284C8 PA_CL_VPORT_ZOFFSET_5 ++0x000284CC PA_CL_VPORT_XSCALE_6 ++0x000284D0 PA_CL_VPORT_XOFFSET_6 ++0x000284D4 PA_CL_VPORT_YSCALE_6 ++0x000284D8 PA_CL_VPORT_YOFFSET_6 ++0x000284DC PA_CL_VPORT_ZSCALE_6 ++0x000284E0 PA_CL_VPORT_ZOFFSET_6 ++0x000284E4 PA_CL_VPORT_XSCALE_7 ++0x000284E8 PA_CL_VPORT_XOFFSET_7 ++0x000284EC PA_CL_VPORT_YSCALE_7 ++0x000284F0 PA_CL_VPORT_YOFFSET_7 ++0x000284F4 PA_CL_VPORT_ZSCALE_7 ++0x000284F8 PA_CL_VPORT_ZOFFSET_7 ++0x000284FC PA_CL_VPORT_XSCALE_8 ++0x00028500 PA_CL_VPORT_XOFFSET_8 ++0x00028504 PA_CL_VPORT_YSCALE_8 ++0x00028508 PA_CL_VPORT_YOFFSET_8 ++0x0002850C PA_CL_VPORT_ZSCALE_8 ++0x00028510 PA_CL_VPORT_ZOFFSET_8 ++0x00028514 PA_CL_VPORT_XSCALE_9 ++0x00028518 PA_CL_VPORT_XOFFSET_9 ++0x0002851C PA_CL_VPORT_YSCALE_9 ++0x00028520 PA_CL_VPORT_YOFFSET_9 ++0x00028524 PA_CL_VPORT_ZSCALE_9 ++0x00028528 PA_CL_VPORT_ZOFFSET_9 ++0x0002852C PA_CL_VPORT_XSCALE_10 ++0x00028530 PA_CL_VPORT_XOFFSET_10 ++0x00028534 PA_CL_VPORT_YSCALE_10 ++0x00028538 PA_CL_VPORT_YOFFSET_10 ++0x0002853C PA_CL_VPORT_ZSCALE_10 ++0x00028540 PA_CL_VPORT_ZOFFSET_10 ++0x00028544 PA_CL_VPORT_XSCALE_11 ++0x00028548 PA_CL_VPORT_XOFFSET_11 ++0x0002854C PA_CL_VPORT_YSCALE_11 ++0x00028550 PA_CL_VPORT_YOFFSET_11 ++0x00028554 PA_CL_VPORT_ZSCALE_11 ++0x00028558 PA_CL_VPORT_ZOFFSET_11 ++0x0002855C PA_CL_VPORT_XSCALE_12 ++0x00028560 PA_CL_VPORT_XOFFSET_12 ++0x00028564 PA_CL_VPORT_YSCALE_12 ++0x00028568 PA_CL_VPORT_YOFFSET_12 ++0x0002856C PA_CL_VPORT_ZSCALE_12 ++0x00028570 PA_CL_VPORT_ZOFFSET_12 ++0x00028574 PA_CL_VPORT_XSCALE_13 ++0x00028578 PA_CL_VPORT_XOFFSET_13 ++0x0002857C PA_CL_VPORT_YSCALE_13 ++0x00028580 PA_CL_VPORT_YOFFSET_13 ++0x00028584 PA_CL_VPORT_ZSCALE_13 ++0x00028588 PA_CL_VPORT_ZOFFSET_13 ++0x0002858C PA_CL_VPORT_XSCALE_14 ++0x00028590 PA_CL_VPORT_XOFFSET_14 ++0x00028594 PA_CL_VPORT_YSCALE_14 ++0x00028598 PA_CL_VPORT_YOFFSET_14 ++0x0002859C PA_CL_VPORT_ZSCALE_14 ++0x000285A0 PA_CL_VPORT_ZOFFSET_14 ++0x000285A4 PA_CL_VPORT_XSCALE_15 ++0x000285A8 PA_CL_VPORT_XOFFSET_15 ++0x000285AC PA_CL_VPORT_YSCALE_15 ++0x000285B0 PA_CL_VPORT_YOFFSET_15 ++0x000285B4 PA_CL_VPORT_ZSCALE_15 ++0x000285B8 PA_CL_VPORT_ZOFFSET_15 ++0x000285BC PA_CL_UCP_0_X ++0x000285C0 PA_CL_UCP_0_Y ++0x000285C4 PA_CL_UCP_0_Z ++0x000285C8 PA_CL_UCP_0_W ++0x000285CC PA_CL_UCP_1_X ++0x000285D0 PA_CL_UCP_1_Y ++0x000285D4 PA_CL_UCP_1_Z ++0x000285D8 PA_CL_UCP_1_W ++0x000285DC PA_CL_UCP_2_X ++0x000285E0 PA_CL_UCP_2_Y ++0x000285E4 PA_CL_UCP_2_Z ++0x000285E8 PA_CL_UCP_2_W ++0x000285EC PA_CL_UCP_3_X ++0x000285F0 PA_CL_UCP_3_Y ++0x000285F4 PA_CL_UCP_3_Z ++0x000285F8 PA_CL_UCP_3_W ++0x000285FC PA_CL_UCP_4_X ++0x00028600 PA_CL_UCP_4_Y ++0x00028604 PA_CL_UCP_4_Z ++0x00028608 PA_CL_UCP_4_W ++0x0002860C PA_CL_UCP_5_X ++0x00028610 PA_CL_UCP_5_Y ++0x00028614 PA_CL_UCP_5_Z ++0x00028618 PA_CL_UCP_5_W ++0x0002861C SPI_VS_OUT_ID_0 ++0x00028620 SPI_VS_OUT_ID_1 ++0x00028624 SPI_VS_OUT_ID_2 ++0x00028628 SPI_VS_OUT_ID_3 ++0x0002862C SPI_VS_OUT_ID_4 ++0x00028630 SPI_VS_OUT_ID_5 ++0x00028634 SPI_VS_OUT_ID_6 ++0x00028638 SPI_VS_OUT_ID_7 ++0x0002863C SPI_VS_OUT_ID_8 ++0x00028640 SPI_VS_OUT_ID_9 ++0x00028644 SPI_PS_INPUT_CNTL_0 ++0x00028648 SPI_PS_INPUT_CNTL_1 ++0x0002864C SPI_PS_INPUT_CNTL_2 ++0x00028650 SPI_PS_INPUT_CNTL_3 ++0x00028654 SPI_PS_INPUT_CNTL_4 ++0x00028658 SPI_PS_INPUT_CNTL_5 ++0x0002865C SPI_PS_INPUT_CNTL_6 ++0x00028660 SPI_PS_INPUT_CNTL_7 ++0x00028664 SPI_PS_INPUT_CNTL_8 ++0x00028668 SPI_PS_INPUT_CNTL_9 ++0x0002866C SPI_PS_INPUT_CNTL_10 ++0x00028670 SPI_PS_INPUT_CNTL_11 ++0x00028674 SPI_PS_INPUT_CNTL_12 ++0x00028678 SPI_PS_INPUT_CNTL_13 ++0x0002867C SPI_PS_INPUT_CNTL_14 ++0x00028680 SPI_PS_INPUT_CNTL_15 ++0x00028684 SPI_PS_INPUT_CNTL_16 ++0x00028688 SPI_PS_INPUT_CNTL_17 ++0x0002868C SPI_PS_INPUT_CNTL_18 ++0x00028690 SPI_PS_INPUT_CNTL_19 ++0x00028694 SPI_PS_INPUT_CNTL_20 ++0x00028698 SPI_PS_INPUT_CNTL_21 ++0x0002869C SPI_PS_INPUT_CNTL_22 ++0x000286A0 SPI_PS_INPUT_CNTL_23 ++0x000286A4 SPI_PS_INPUT_CNTL_24 ++0x000286A8 SPI_PS_INPUT_CNTL_25 ++0x000286AC SPI_PS_INPUT_CNTL_26 ++0x000286B0 SPI_PS_INPUT_CNTL_27 ++0x000286B4 SPI_PS_INPUT_CNTL_28 ++0x000286B8 SPI_PS_INPUT_CNTL_29 ++0x000286BC SPI_PS_INPUT_CNTL_30 ++0x000286C0 SPI_PS_INPUT_CNTL_31 ++0x000286C4 SPI_VS_OUT_CONFIG ++0x000286C8 SPI_THREAD_GROUPING ++0x000286CC SPI_PS_IN_CONTROL_0 ++0x000286D0 SPI_PS_IN_CONTROL_1 ++0x000286D4 SPI_INTERP_CONTROL_0 ++0x000286D8 SPI_INPUT_Z ++0x000286DC SPI_FOG_CNTL ++0x000286E0 SPI_BARYC_CNTL ++0x000286E4 SPI_PS_IN_CONTROL_2 ++0x000286E8 SPI_COMPUTE_INPUT_CNTL ++0x000286EC SPI_COMPUTE_NUM_THREAD_X ++0x000286F0 SPI_COMPUTE_NUM_THREAD_Y ++0x000286F4 SPI_COMPUTE_NUM_THREAD_Z ++0x000286F8 SPI_GPR_MGMT ++0x000286FC SPI_LDS_MGMT ++0x00028700 SPI_STACK_MGMT ++0x00028704 SPI_WAVE_MGMT_1 ++0x00028708 SPI_WAVE_MGMT_2 ++0x00028724 GDS_ADDR_SIZE ++0x00028780 CB_BLEND0_CONTROL ++0x00028784 CB_BLEND1_CONTROL ++0x00028788 CB_BLEND2_CONTROL ++0x0002878C CB_BLEND3_CONTROL ++0x00028790 CB_BLEND4_CONTROL ++0x00028794 CB_BLEND5_CONTROL ++0x00028798 CB_BLEND6_CONTROL ++0x0002879C CB_BLEND7_CONTROL ++0x000287CC CS_COPY_STATE ++0x000287D0 GFX_COPY_STATE ++0x000287D4 PA_CL_POINT_X_RAD ++0x000287D8 PA_CL_POINT_Y_RAD ++0x000287DC PA_CL_POINT_SIZE ++0x000287E0 PA_CL_POINT_CULL_RAD ++0x00028808 CB_COLOR_CONTROL ++0x0002880C DB_SHADER_CONTROL ++0x00028810 PA_CL_CLIP_CNTL ++0x00028814 PA_SU_SC_MODE_CNTL ++0x00028818 PA_CL_VTE_CNTL ++0x0002881C PA_CL_VS_OUT_CNTL ++0x00028820 PA_CL_NANINF_CNTL ++0x00028824 PA_SU_LINE_STIPPLE_CNTL ++0x00028828 PA_SU_LINE_STIPPLE_SCALE ++0x0002882C PA_SU_PRIM_FILTER_CNTL ++0x00028844 SQ_PGM_RESOURCES_PS ++0x00028848 SQ_PGM_RESOURCES_2_PS ++0x0002884C SQ_PGM_EXPORTS_PS ++0x00028860 SQ_PGM_RESOURCES_VS ++0x00028864 SQ_PGM_RESOURCES_2_VS ++0x00028878 SQ_PGM_RESOURCES_GS ++0x0002887C SQ_PGM_RESOURCES_2_GS ++0x00028890 SQ_PGM_RESOURCES_ES ++0x00028894 SQ_PGM_RESOURCES_2_ES ++0x000288A8 SQ_PGM_RESOURCES_FS ++0x000288BC SQ_PGM_RESOURCES_HS ++0x000288C0 SQ_PGM_RESOURCES_2_HS ++0x000288D4 SQ_PGM_RESOURCES_LS ++0x000288D8 SQ_PGM_RESOURCES_2_LS ++0x000288E8 SQ_LDS_ALLOC ++0x000288EC SQ_LDS_ALLOC_PS ++0x000288F0 SQ_VTX_SEMANTIC_CLEAR ++0x00028A00 PA_SU_POINT_SIZE ++0x00028A04 PA_SU_POINT_MINMAX ++0x00028A08 PA_SU_LINE_CNTL ++0x00028A0C PA_SC_LINE_STIPPLE ++0x00028A10 VGT_OUTPUT_PATH_CNTL ++0x00028A14 VGT_HOS_CNTL ++0x00028A18 VGT_HOS_MAX_TESS_LEVEL ++0x00028A1C VGT_HOS_MIN_TESS_LEVEL ++0x00028A20 VGT_HOS_REUSE_DEPTH ++0x00028A24 VGT_GROUP_PRIM_TYPE ++0x00028A28 VGT_GROUP_FIRST_DECR ++0x00028A2C VGT_GROUP_DECR ++0x00028A30 VGT_GROUP_VECT_0_CNTL ++0x00028A34 VGT_GROUP_VECT_1_CNTL ++0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL ++0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL ++0x00028A40 VGT_GS_MODE ++0x00028A48 PA_SC_MODE_CNTL_0 ++0x00028A4C PA_SC_MODE_CNTL_1 ++0x00028A50 VGT_ENHANCE ++0x00028A54 VGT_GS_PER_ES ++0x00028A58 VGT_ES_PER_GS ++0x00028A5C VGT_GS_PER_VS ++0x00028A6C VGT_GS_OUT_PRIM_TYPE ++0x00028A70 IA_ENHANCE ++0x00028A84 VGT_PRIMITIVEID_EN ++0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN ++0x00028AA0 VGT_INSTANCE_STEP_RATE_0 ++0x00028AA4 VGT_INSTANCE_STEP_RATE_1 ++0x00028AA8 IA_MULTI_VGT_PARAM ++0x00028AB4 VGT_REUSE_OFF ++0x00028AB8 VGT_VTX_CNT_EN ++0x00028ABC DB_HTILE_SURFACE ++0x00028AC0 DB_SRESULTS_COMPARE_STATE0 ++0x00028AC4 DB_SRESULTS_COMPARE_STATE1 ++0x00028AC8 DB_PRELOAD_CONTROL ++0x00028B38 VGT_GS_MAX_VERT_OUT ++0x00028B54 VGT_SHADER_STAGES_EN ++0x00028B58 VGT_LS_HS_CONFIG ++0x00028B6C VGT_TF_PARAM ++0x00028B70 DB_ALPHA_TO_MASK ++0x00028B74 VGT_DISPATCH_INITIATOR ++0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL ++0x00028B7C PA_SU_POLY_OFFSET_CLAMP ++0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE ++0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET ++0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE ++0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET ++0x00028B74 VGT_GS_INSTANCE_CNT ++0x00028BD4 PA_SC_CENTROID_PRIORITY_0 ++0x00028BD8 PA_SC_CENTROID_PRIORITY_1 ++0x00028BDC PA_SC_LINE_CNTL ++0x00028BE4 PA_SU_VTX_CNTL ++0x00028BE8 PA_CL_GB_VERT_CLIP_ADJ ++0x00028BEC PA_CL_GB_VERT_DISC_ADJ ++0x00028BF0 PA_CL_GB_HORZ_CLIP_ADJ ++0x00028BF4 PA_CL_GB_HORZ_DISC_ADJ ++0x00028BF8 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_0 ++0x00028BFC PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_1 ++0x00028C00 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_2 ++0x00028C04 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_3 ++0x00028C08 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_0 ++0x00028C0C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_1 ++0x00028C10 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_2 ++0x00028C14 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_3 ++0x00028C18 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_0 ++0x00028C1C PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_1 ++0x00028C20 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_2 ++0x00028C24 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_3 ++0x00028C28 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_0 ++0x00028C2C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_1 ++0x00028C30 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_2 ++0x00028C34 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_3 ++0x00028C38 PA_SC_AA_MASK_X0_Y0_X1_Y0 ++0x00028C3C PA_SC_AA_MASK_X0_Y1_X1_Y1 ++0x00028C8C CB_COLOR0_CLEAR_WORD0 ++0x00028C90 CB_COLOR0_CLEAR_WORD1 ++0x00028C94 CB_COLOR0_CLEAR_WORD2 ++0x00028C98 CB_COLOR0_CLEAR_WORD3 ++0x00028CC8 CB_COLOR1_CLEAR_WORD0 ++0x00028CCC CB_COLOR1_CLEAR_WORD1 ++0x00028CD0 CB_COLOR1_CLEAR_WORD2 ++0x00028CD4 CB_COLOR1_CLEAR_WORD3 ++0x00028D04 CB_COLOR2_CLEAR_WORD0 ++0x00028D08 CB_COLOR2_CLEAR_WORD1 ++0x00028D0C CB_COLOR2_CLEAR_WORD2 ++0x00028D10 CB_COLOR2_CLEAR_WORD3 ++0x00028D40 CB_COLOR3_CLEAR_WORD0 ++0x00028D44 CB_COLOR3_CLEAR_WORD1 ++0x00028D48 CB_COLOR3_CLEAR_WORD2 ++0x00028D4C CB_COLOR3_CLEAR_WORD3 ++0x00028D7C CB_COLOR4_CLEAR_WORD0 ++0x00028D80 CB_COLOR4_CLEAR_WORD1 ++0x00028D84 CB_COLOR4_CLEAR_WORD2 ++0x00028D88 CB_COLOR4_CLEAR_WORD3 ++0x00028DB8 CB_COLOR5_CLEAR_WORD0 ++0x00028DBC CB_COLOR5_CLEAR_WORD1 ++0x00028DC0 CB_COLOR5_CLEAR_WORD2 ++0x00028DC4 CB_COLOR5_CLEAR_WORD3 ++0x00028DF4 CB_COLOR6_CLEAR_WORD0 ++0x00028DF8 CB_COLOR6_CLEAR_WORD1 ++0x00028DFC CB_COLOR6_CLEAR_WORD2 ++0x00028E00 CB_COLOR6_CLEAR_WORD3 ++0x00028E30 CB_COLOR7_CLEAR_WORD0 ++0x00028E34 CB_COLOR7_CLEAR_WORD1 ++0x00028E38 CB_COLOR7_CLEAR_WORD2 ++0x00028E3C CB_COLOR7_CLEAR_WORD3 ++0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0 ++0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1 ++0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2 ++0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3 ++0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4 ++0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5 ++0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6 ++0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7 ++0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8 ++0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9 ++0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10 ++0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11 ++0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12 ++0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13 ++0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14 ++0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15 ++0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0 ++0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1 ++0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2 ++0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3 ++0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4 ++0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5 ++0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6 ++0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7 ++0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8 ++0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9 ++0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10 ++0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11 ++0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12 ++0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13 ++0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14 ++0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15 ++0x0003CFF0 SQ_VTX_BASE_VTX_LOC ++0x0003CFF4 SQ_VTX_START_INST_LOC ++0x0003FF00 SQ_TEX_SAMPLER_CLEAR ++0x0003FF04 SQ_TEX_RESOURCE_CLEAR ++0x0003FF08 SQ_LOOP_BOOL_CLEAR +diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen +index 9177f91..7e16371 100644 +--- a/drivers/gpu/drm/radeon/reg_srcs/evergreen ++++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen +@@ -1,4 +1,5 @@ + evergreen 0x9400 ++0x0000802C GRBM_GFX_INDEX + 0x00008040 WAIT_UNTIL + 0x00008044 WAIT_UNTIL_POLL_CNTL + 0x00008048 WAIT_UNTIL_POLL_MASK +@@ -220,6 +221,7 @@ evergreen 0x9400 + 0x00028348 PA_SC_VPORT_ZMIN_15 + 0x0002834C PA_SC_VPORT_ZMAX_15 + 0x00028350 SX_MISC ++0x00028354 SX_SURFACE_SYNC + 0x00028380 SQ_VTX_SEMANTIC_0 + 0x00028384 SQ_VTX_SEMANTIC_1 + 0x00028388 SQ_VTX_SEMANTIC_2 +diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 +index af0da4a..92f1900 100644 +--- a/drivers/gpu/drm/radeon/reg_srcs/r600 ++++ b/drivers/gpu/drm/radeon/reg_srcs/r600 +@@ -708,6 +708,7 @@ r600 0x9400 + 0x00028D0C DB_RENDER_CONTROL + 0x00028D10 DB_RENDER_OVERRIDE + 0x0002880C DB_SHADER_CONTROL ++0x00028D28 DB_SRESULTS_COMPARE_STATE0 + 0x00028D2C DB_SRESULTS_COMPARE_STATE1 + 0x00028430 DB_STENCILREFMASK + 0x00028434 DB_STENCILREFMASK_BF +diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c +index 8af4679..c55cf2a 100644 +--- a/drivers/gpu/drm/radeon/rs600.c ++++ b/drivers/gpu/drm/radeon/rs600.c +@@ -48,17 +48,6 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev); + + void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) + { +- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; +- u32 tmp; +- +- /* make sure flip is at vb rather than hb */ +- tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); +- tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; +- WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); +- +- /* set pageflip to happen anywhere in vblank interval */ +- WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); +- + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); + } +@@ -125,7 +114,7 @@ void rs600_pm_misc(struct radeon_device *rdev) + udelay(voltage->delay); + } + } else if (voltage->type == VOLTAGE_VDDC) +- radeon_atom_set_voltage(rdev, voltage->vddc_id); ++ radeon_atom_set_voltage(rdev, voltage->vddc_id, SET_VOLTAGE_TYPE_ASIC_VDDC); + + dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH); + dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf); +diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c +index 714ad45..114e5cc 100644 +--- a/drivers/gpu/drm/radeon/rv770.c ++++ b/drivers/gpu/drm/radeon/rv770.c +@@ -106,7 +106,7 @@ void rv770_pm_misc(struct radeon_device *rdev) + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { + if (voltage->voltage != rdev->pm.current_vddc) { +- radeon_atom_set_voltage(rdev, voltage->voltage); ++ radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG("Setting: v: %d\n", voltage->voltage); + } +diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h +index e5c607a..32c8e1c 100644 +--- a/include/drm/radeon_drm.h ++++ b/include/drm/radeon_drm.h +@@ -908,6 +908,9 @@ struct drm_radeon_cs { + #define RADEON_INFO_WANT_HYPERZ 0x07 + #define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ + #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ ++#define RADEON_INFO_NUM_BACKENDS 0x0a /* DB/backends for r600+ - need for OQ */ ++#define RADEON_INFO_NUM_TILE_PIPES 0x0b /* tile pipes for r600+ */ ++#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ + + struct drm_radeon_info { + uint32_t request; diff --git a/drm-vblank-events-fix-hangs.patch b/drm-vblank-events-fix-hangs.patch new file mode 100644 index 000000000..1148f4e3c --- /dev/null +++ b/drm-vblank-events-fix-hangs.patch @@ -0,0 +1,60 @@ +From 498548ec69c6897fe4376b2ca90758762fa0b817 Mon Sep 17 00:00:00 2001 +From: Christopher James Halse Rogers +Date: Wed, 27 Apr 2011 16:10:57 +1000 +Subject: [PATCH 3/4] drm: Send pending vblank events before disabling vblank. + +This is the least-bad behaviour. It means that we signal the +vblank event before it actually happens, but since we're disabling +vblanks there's no guarantee that it will *ever* happen otherwise. + +This prevents GL applications which use WaitMSC from hanging +indefinitely. + +Signed-off-by: Christopher James Halse Rogers +Signed-off-by: Dave Airlie +--- + drivers/gpu/drm/drm_irq.c | 23 +++++++++++++++++++++++ + 1 files changed, 23 insertions(+), 0 deletions(-) + +diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c +index 741457b..a1f12cb 100644 +--- a/drivers/gpu/drm/drm_irq.c ++++ b/drivers/gpu/drm/drm_irq.c +@@ -932,11 +932,34 @@ EXPORT_SYMBOL(drm_vblank_put); + + void drm_vblank_off(struct drm_device *dev, int crtc) + { ++ struct drm_pending_vblank_event *e, *t; ++ struct timeval now; + unsigned long irqflags; ++ unsigned int seq; + + spin_lock_irqsave(&dev->vbl_lock, irqflags); + vblank_disable_and_save(dev, crtc); + DRM_WAKEUP(&dev->vbl_queue[crtc]); ++ ++ /* Send any queued vblank events, lest the natives grow disquiet */ ++ seq = drm_vblank_count_and_time(dev, crtc, &now); ++ list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { ++ if (e->pipe != crtc) ++ continue; ++ DRM_DEBUG("Sending premature vblank event on disable: \ ++ wanted %d, current %d\n", ++ e->event.sequence, seq); ++ ++ e->event.sequence = seq; ++ e->event.tv_sec = now.tv_sec; ++ e->event.tv_usec = now.tv_usec; ++ drm_vblank_put(dev, e->pipe); ++ list_move_tail(&e->base.link, &e->base.file_priv->event_list); ++ wake_up_interruptible(&e->base.file_priv->event_wait); ++ trace_drm_vblank_event_delivered(e->base.pid, e->pipe, ++ e->event.sequence); ++ } ++ + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + } + EXPORT_SYMBOL(drm_vblank_off); +-- +1.7.1 + diff --git a/kernel.spec b/kernel.spec index 233f78229..76503eb25 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 22 +%global baserelease 23 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -668,6 +668,7 @@ Patch800: linux-2.6-crash-driver.patch Patch1555: fix_xen_guest_on_old_EC2.patch # DRM +Patch1800: drm-vblank-events-fix-hangs.patch # nouveau + drm fixes Patch1809: drm-nouveau-fixes.patch @@ -682,6 +683,8 @@ Patch1824: drm-intel-next.patch Patch1825: drm-intel-make-lvds-work.patch Patch1826: drm-intel-edp-fixes.patch Patch1828: drm-intel-eeebox-eb1007-quirk.patch +# radeon - new hw + fixes for fusion and t500 regression +Patch1840: drm-radeon-update.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1301,6 +1304,7 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core +ApplyPatch drm-vblank-events-fix-hangs.patch # Nouveau DRM ApplyPatch drm-ttm-move-notify.patch @@ -1316,6 +1320,9 @@ ApplyPatch drm-intel-edp-fixes.patch ApplyPatch drm-i915-fix-pipelined-fencing.patch ApplyPatch drm-intel-eeebox-eb1007-quirk.patch +# radeon DRM (add cayman support) +ApplyPatch drm-radeon-update.patch + # linux1394 git patches #ApplyPatch linux-2.6-firewire-git-update.patch #ApplyOptionalPatch linux-2.6-firewire-git-pending.patch @@ -1972,6 +1979,10 @@ fi # and build. %changelog +* Tue May 03 2011 Dave Airlie 2.6.38.5-23 +- radeon updates from 2.6.39 with cayman + fixes for lots of things including Fusion. +- vblank fix for core drm + * Mon May 02 2011 Chuck Ebbert - [SCSI] mpt2sas: prevent heap overflows and unchecked reads (CVE-2011-1494, CVE-2011-1495) From 9da2734a4b2a6d6bfad80b347d9ea26f5aa2d5c5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 6 May 2011 03:29:13 -0400 Subject: [PATCH 46/99] forgot the cayman PCI IDs. --- drm-radeon-update.patch | 28 ++++++++++++++++++++++++++++ kernel.spec | 5 ++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drm-radeon-update.patch b/drm-radeon-update.patch index 8725c021b..205141407 100644 --- a/drm-radeon-update.patch +++ b/drm-radeon-update.patch @@ -4805,3 +4805,31 @@ index e5c607a..32c8e1c 100644 struct drm_radeon_info { uint32_t request; +diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h +index 6724bf3..816e30c 100644 +--- a/include/drm/drm_pciids.h ++++ b/include/drm/drm_pciids.h +@@ -141,6 +141,20 @@ + {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6703, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6704, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6705, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6706, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6707, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6708, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6709, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6718, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x6719, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x671c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ ++ {0x1002, 0x671d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6721, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6722, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \ +-- +1.7.1 + diff --git a/kernel.spec b/kernel.spec index 76503eb25..2597ec0f9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 23 +%global baserelease 24 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1979,6 +1979,9 @@ fi # and build. %changelog +* Fri May 06 2011 Dave Airlie 2.6.38.5-24 +- forgot the cayman PCI IDs. + * Tue May 03 2011 Dave Airlie 2.6.38.5-23 - radeon updates from 2.6.39 with cayman + fixes for lots of things including Fusion. - vblank fix for core drm From 9057ac9c23fe4113da959ac273f62e8f404c410d Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 7 May 2011 05:52:33 -0400 Subject: [PATCH 47/99] Fix breakage of network device names on Dell systems (#702740) --- kernel.spec | 11 +++- ...ci-bfsort-whitelist-for-dell-systems.patch | 55 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch diff --git a/kernel.spec b/kernel.spec index 2597ec0f9..37f0e12d6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -735,10 +735,12 @@ Patch12401: scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch # CVE-2011-1581 Patch12402: bonding-incorrect-tx-queue-offset.patch -# Restore reliable stack backtraces, and hopefully -# fix RHBZ #700718 +# Restore reliable stack backtraces, and hopefully fix RHBZ #700718 Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch +# Fix breakage of PCI network adapter names on older Dell systems +Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1251,6 +1253,8 @@ ApplyPatch linux-2.6-defaults-aspm.patch # fixes for ASPM powersave mode ApplyPatch pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch ApplyPatch pci-enable-aspm-state-clearing-regardless-of-policy.patch +# Fix breakage of PCI network adapter names on older Dell systems +ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch #ApplyPatch ima-allow-it-to-be-completely-disabled-and-default-off.patch @@ -1979,6 +1983,9 @@ fi # and build. %changelog +* Sat May 07 2011 Chuck Ebbert +- Fix breakage of network device names on Dell systems (#702740) + * Fri May 06 2011 Dave Airlie 2.6.38.5-24 - forgot the cayman PCI IDs. diff --git a/x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch b/x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch new file mode 100644 index 000000000..9cedbadf9 --- /dev/null +++ b/x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch @@ -0,0 +1,55 @@ +From: Narendra K +Subject: [PATCH] x86/PCI: Preserve existing pci=bfsort whitelist for Dell systems. + +Commit 6e8af08dfa40b747002207d3ce8e8b43a050d99f enables pci=bfsort on +future Dell systems. But the identification string 'Dell System' matches +on already existing whitelist, which do not have SMBIOS type 0xB1, +causing pci=bfsort not being set on existing whitelist. + +This patch fixes the regression by moving the type 0xB1 check beyond the +existing whitelist so that existing whitelist is walked before. + +Signed-off-by: Shyam Iyer +Signed-off-by: Narendra K +--- +RHBZ #702740 +http://marc.info/?l=linux-pci&m=130046899115205&q=raw + + arch/x86/pci/common.c | 14 +++++++------- + 1 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c +index 5fe7502..92df322 100644 +--- a/arch/x86/pci/common.c ++++ b/arch/x86/pci/common.c +@@ -247,13 +247,6 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = { + }, + #endif /* __i386__ */ + { +- .callback = find_sort_method, +- .ident = "Dell System", +- .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), +- }, +- }, +- { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 1950", + .matches = { +@@ -294,6 +287,13 @@ static const struct dmi_system_id __devinitconst pciprobe_dmi_table[] = { + }, + }, + { ++ .callback = find_sort_method, ++ .ident = "Dell System", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), ++ }, ++ }, ++ { + .callback = set_bf_sort, + .ident = "HP ProLiant BL20p G3", + .matches = { +-- +1.7.3.1 + From 7f205bd4859bc5c76076facfcd974f6a52349cc4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 9 May 2011 12:05:27 +1000 Subject: [PATCH 48/99] fix dual-gpu intel/radeon laptops where intel would cause radeon crash. --- drm-intel-restore-mode.patch | 128 +++++++++++++++++++++++++++++++++++ kernel.spec | 5 ++ 2 files changed, 133 insertions(+) create mode 100644 drm-intel-restore-mode.patch diff --git a/drm-intel-restore-mode.patch b/drm-intel-restore-mode.patch new file mode 100644 index 000000000..b394ca00d --- /dev/null +++ b/drm-intel-restore-mode.patch @@ -0,0 +1,128 @@ +From e8e7a2b8ccfdae0d4cb6bd25824bbedcd42da316 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Thu, 21 Apr 2011 22:18:32 +0100 +Subject: [PATCH] drm/i915: restore only the mode of this driver on lastclose (v2) + +i915 calls the panic handler function on last close to reset the modes, +however this is a really bad idea for multi-gpu machines, esp shareable +gpus machines. So add a new entry point for the driver to just restore +its own fbcon mode. + +v2: move code into fb helper, fix panic code to block mode change on +powered off GPUs. + +[airlied: this hits drm core and I wrote it and it was reviewed on intel-gfx + so really I signed it off twice ;-).] +Signed-off-by: Chris Wilson +Signed-off-by: Dave Airlie +--- + drivers/gpu/drm/drm_fb_helper.c | 27 ++++++++++++++++++++------- + drivers/gpu/drm/i915/i915_dma.c | 2 +- + drivers/gpu/drm/i915/intel_drv.h | 1 + + drivers/gpu/drm/i915/intel_fb.c | 10 ++++++++++ + include/drm/drm_fb_helper.h | 1 + + 5 files changed, 33 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c +index 9507204..11d7a72 100644 +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -342,9 +342,22 @@ int drm_fb_helper_debug_leave(struct fb_info *info) + } + EXPORT_SYMBOL(drm_fb_helper_debug_leave); + ++bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) ++{ ++ bool error = false; ++ int i, ret; ++ for (i = 0; i < fb_helper->crtc_count; i++) { ++ struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; ++ ret = drm_crtc_helper_set_config(mode_set); ++ if (ret) ++ error = true; ++ } ++ return error; ++} ++EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode); ++ + bool drm_fb_helper_force_kernel_mode(void) + { +- int i = 0; + bool ret, error = false; + struct drm_fb_helper *helper; + +@@ -352,12 +365,12 @@ bool drm_fb_helper_force_kernel_mode(void) + return false; + + list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { +- for (i = 0; i < helper->crtc_count; i++) { +- struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; +- ret = drm_crtc_helper_set_config(mode_set); +- if (ret) +- error = true; +- } ++ if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF) ++ continue; ++ ++ ret = drm_fb_helper_restore_fbdev_mode(helper); ++ if (ret) ++ error = true; + } + return error; + } +diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c +index 7273037..12876f2 100644 +--- a/drivers/gpu/drm/i915/i915_dma.c ++++ b/drivers/gpu/drm/i915/i915_dma.c +@@ -2207,7 +2207,7 @@ void i915_driver_lastclose(struct drm_device * dev) + drm_i915_private_t *dev_priv = dev->dev_private; + + if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { +- drm_fb_helper_restore(); ++ intel_fb_restore_mode(dev); + vga_switcheroo_process_delayed_switch(); + return; + } +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index f5b0d83..1d20712 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -338,4 +338,5 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data, + struct drm_file *file_priv); + + extern void intel_fb_output_poll_changed(struct drm_device *dev); ++extern void intel_fb_restore_mode(struct drm_device *dev); + #endif /* __INTEL_DRV_H__ */ +diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c +index 5127827..ec49bae 100644 +--- a/drivers/gpu/drm/i915/intel_fb.c ++++ b/drivers/gpu/drm/i915/intel_fb.c +@@ -264,3 +264,13 @@ void intel_fb_output_poll_changed(struct drm_device *dev) + drm_i915_private_t *dev_priv = dev->dev_private; + drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); + } ++ ++void intel_fb_restore_mode(struct drm_device *dev) ++{ ++ int ret; ++ drm_i915_private_t *dev_priv = dev->dev_private; ++ ++ ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); ++ if (ret) ++ DRM_DEBUG("failed to restore crtc mode\n"); ++} +diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h +index f22e7fe..ade09d7 100644 +--- a/include/drm/drm_fb_helper.h ++++ b/include/drm/drm_fb_helper.h +@@ -118,6 +118,7 @@ int drm_fb_helper_setcolreg(unsigned regno, + unsigned transp, + struct fb_info *info); + ++bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper); + void drm_fb_helper_restore(void); + void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, + uint32_t fb_width, uint32_t fb_height); +-- +1.7.1 + diff --git a/kernel.spec b/kernel.spec index 37f0e12d6..6c723874f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -683,6 +683,7 @@ Patch1824: drm-intel-next.patch Patch1825: drm-intel-make-lvds-work.patch Patch1826: drm-intel-edp-fixes.patch Patch1828: drm-intel-eeebox-eb1007-quirk.patch +Patch1829: drm-intel-restore-mode.patch # radeon - new hw + fixes for fusion and t500 regression Patch1840: drm-radeon-update.patch @@ -1323,6 +1324,7 @@ ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch drm-intel-edp-fixes.patch ApplyPatch drm-i915-fix-pipelined-fencing.patch ApplyPatch drm-intel-eeebox-eb1007-quirk.patch +ApplyPatch drm-intel-restore-mode.patch # radeon DRM (add cayman support) ApplyPatch drm-radeon-update.patch @@ -1983,6 +1985,9 @@ fi # and build. %changelog +* Mon May 09 2011 Dave Airlie +- fix dual-gpu intel/radeon laptops where intel would cause radeon crash. + * Sat May 07 2011 Chuck Ebbert - Fix breakage of network device names on Dell systems (#702740) From d470023c151ff49ed3f97eeec66f1874d3322af1 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 9 May 2011 07:38:25 -0400 Subject: [PATCH 49/99] Enable CONFIG_FB_UDL (#634636) (copy from rawhide) --- config-generic | 2 +- kernel.spec | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config-generic b/config-generic index de1ee3763..d9a64445f 100644 --- a/config-generic +++ b/config-generic @@ -4393,7 +4393,7 @@ CONFIG_NTP_PPS=y # CONFIG_USB_SERIAL_QUATECH2 is not set # CONFIG_VT6655 is not set -# CONFIG_FB_UDL is not set +CONFIG_FB_UDL=m # DEBUG options that don't get enabled/disabled with 'make debug/release' # diff --git a/kernel.spec b/kernel.spec index 6c723874f..f12db1bba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1985,6 +1985,9 @@ fi # and build. %changelog +* Mon May 08 2011 Chuck Ebbert +- Enable CONFIG_FB_UDL (#634636) + * Mon May 09 2011 Dave Airlie - fix dual-gpu intel/radeon laptops where intel would cause radeon crash. From ee720e953929b92af8cf4ffad38046b8c6396997 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 9 May 2011 10:57:08 -0400 Subject: [PATCH 50/99] doh, fix date --- kernel.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index f12db1bba..ec720d52f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1985,7 +1985,7 @@ fi # and build. %changelog -* Mon May 08 2011 Chuck Ebbert +* Mon May 09 2011 Chuck Ebbert - Enable CONFIG_FB_UDL (#634636) * Mon May 09 2011 Dave Airlie From 5c3a39fd9a51511d63280c3fb04d7f5fcfbef6fc Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 9 May 2011 10:59:06 -0400 Subject: [PATCH 51/99] update to stable-review 2.6.38.6-rc1 --- ...sing-socket-check-in-can_raw_release.patch | 39 +++++++++ cx88-Fix-HVR4000-IR-keymap.patch | 55 ++++++++++++ ...tom-cards-with-hardcoded-EDID-record.patch | 56 +++++++++++++ kernel.spec | 32 +++++-- scsi-fix-oops-in-scsi_run_queue.patch | 49 +++++++++++ ...t-heap-overflows-and-unchecked-reads.patch | 83 ------------------- sources | 1 + 7 files changed, 223 insertions(+), 92 deletions(-) create mode 100644 can-add-missing-socket-check-in-can_raw_release.patch create mode 100644 cx88-Fix-HVR4000-IR-keymap.patch create mode 100644 drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch create mode 100644 scsi-fix-oops-in-scsi_run_queue.patch delete mode 100644 scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch diff --git a/can-add-missing-socket-check-in-can_raw_release.patch b/can-add-missing-socket-check-in-can_raw_release.patch new file mode 100644 index 000000000..b960fd5a1 --- /dev/null +++ b/can-add-missing-socket-check-in-can_raw_release.patch @@ -0,0 +1,39 @@ +From b3be9dcd312f13563b68d0432830ef94dd3b33de Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Wed, 20 Apr 2011 01:57:15 +0000 +Subject: [PATCH] can: add missing socket check in can/raw release + +v2: added space after 'if' according code style. + +We can get here with a NULL socket argument passed from userspace, +so we need to handle it accordingly. + +Thanks to Dave Jones pointing at this issue in net/can/bcm.c + +Signed-off-by: Oliver Hartkopp +Signed-off-by: David S. Miller +--- + net/can/raw.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/net/can/raw.c b/net/can/raw.c +index 883e9d7..241b2b6 100644 +--- a/net/can/raw.c ++++ b/net/can/raw.c +@@ -305,7 +305,12 @@ static int raw_init(struct sock *sk) + static int raw_release(struct socket *sock) + { + struct sock *sk = sock->sk; +- struct raw_sock *ro = raw_sk(sk); ++ struct raw_sock *ro; ++ ++ if (!sk) ++ return 0; ++ ++ ro = raw_sk(sk); + + unregister_netdevice_notifier(&ro->notifier); + +-- +1.7.5.1 + diff --git a/cx88-Fix-HVR4000-IR-keymap.patch b/cx88-Fix-HVR4000-IR-keymap.patch new file mode 100644 index 000000000..b145cd29c --- /dev/null +++ b/cx88-Fix-HVR4000-IR-keymap.patch @@ -0,0 +1,55 @@ +From linux-kernel-owner@vger.kernel.org Thu May 5 20:14:44 2011 +Date: Thu, 05 May 2011 17:11:08 -0700 +From: Greg KH +To: linux-kernel@vger.kernel.org, stable@kernel.org, + Greg KH +Cc: stable-review@kernel.org, torvalds@linux-foundation.org, + akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, + Jarod Wilson , + Lawrence Rust , + Linux Media Mailing List , + Lawrence Rust , + Mauro Carvalho Chehab +Subject: [patch 36/38] [media] cx88: Fix HVR4000 IR keymap +In-Reply-To: <20110506001225.GA10547@kroah.com> +X-Mailing-List: linux-kernel@vger.kernel.org + +2.6.38-stable review patch. If anyone has any objections, please let us know. + +------------------ + +From: Lawrence Rust + +[fixed in .39 in a much different way that is too big to backport to +.38 - gregkh] + +Fixes the RC key input for Nova-S plus, HVR1100, HVR3000 and HVR4000 in +the 2.6.38 kernel. + +Signed-off-by: Lawrence Rust +Acked-by: Jarod Wilson +Signed-off-by: Mauro Carvalho Chehab + +--- + drivers/media/video/cx88/cx88-input.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/video/cx88/cx88-input.c ++++ b/drivers/media/video/cx88/cx88-input.c +@@ -283,7 +283,7 @@ int cx88_ir_init(struct cx88_core *core, + case CX88_BOARD_PCHDTV_HD3000: + case CX88_BOARD_PCHDTV_HD5500: + case CX88_BOARD_HAUPPAUGE_IRONLY: +- ir_codes = RC_MAP_HAUPPAUGE_NEW; ++ ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; + ir->sampling = 1; + break; + case CX88_BOARD_WINFAST_DTV2000H: + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ + diff --git a/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch b/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch new file mode 100644 index 000000000..217e29d76 --- /dev/null +++ b/drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch @@ -0,0 +1,56 @@ +From linux-kernel-owner@vger.kernel.org Thu May 5 20:17:19 2011 +Date: Thu, 05 May 2011 17:10:51 -0700 +From: Greg KH +To: linux-kernel@vger.kernel.org, stable@kernel.org +Cc: stable-review@kernel.org, torvalds@linux-foundation.org, + akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, + Dave Airlie +Subject: [patch 19/38] drm/radeon: fix regression on atom cards with hardcoded EDID record. +In-Reply-To: <20110506001225.GA10547@kroah.com> +X-Mailing-List: linux-kernel@vger.kernel.org + +2.6.38-stable review patch. If anyone has any objections, please let us know. + +------------------ + +From: Dave Airlie + +commit eaa4f5e1d0b816291a59a47917e569c0384f2b6f upstream. + +Since fafcf94e2b5732d1e13b440291c53115d2b172e9 introduced an edid size, it seems to have broken this path. + +This manifest as oops on T500 Lenovo laptops with dual graphics primarily. + +Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33812 + +Reviewed-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_atombios.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -1599,9 +1599,10 @@ struct radeon_encoder_atom_dig *radeon_a + memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], + fake_edid_record->ucFakeEDIDLength); + +- if (drm_edid_is_valid(edid)) ++ if (drm_edid_is_valid(edid)) { + rdev->mode_info.bios_hardcoded_edid = edid; +- else ++ rdev->mode_info.bios_hardcoded_edid_size = edid_size; ++ } else + kfree(edid); + } + } + + +-- +To unsubscribe from this list: send the line "unsubscribe linux-kernel" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html +Please read the FAQ at http://www.tux.org/lkml/ + diff --git a/kernel.spec b/kernel.spec index ec720d52f..43db90ea2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 24 +%global baserelease 25 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,9 +63,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 5 +%define stable_update 6 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -685,6 +685,7 @@ Patch1826: drm-intel-edp-fixes.patch Patch1828: drm-intel-eeebox-eb1007-quirk.patch Patch1829: drm-intel-restore-mode.patch # radeon - new hw + fixes for fusion and t500 regression +Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch Patch1840: drm-radeon-update.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -698,6 +699,7 @@ Patch2201: linux-2.6-firewire-git-pending.patch Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches +Patch2898: cx88-Fix-HVR4000-IR-keymap.patch Patch2899: linux-2.6-v4l-dvb-fixes.patch Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch @@ -730,9 +732,6 @@ Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch #netconsole fixes Patch12400: linux-2.6-netconsole-deadlock.patch -# CVE-2011-1494, CVE-2011-1495 -Patch12401: scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch - # CVE-2011-1581 Patch12402: bonding-incorrect-tx-queue-offset.patch @@ -742,6 +741,10 @@ Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-availabl # Fix breakage of PCI network adapter names on older Dell systems Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch +Patch12410: scsi-fix-oops-in-scsi_run_queue.patch + +Patch12420: can-add-missing-socket-check-in-can_raw_release.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1327,6 +1330,7 @@ ApplyPatch drm-intel-eeebox-eb1007-quirk.patch ApplyPatch drm-intel-restore-mode.patch # radeon DRM (add cayman support) +ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -R ApplyPatch drm-radeon-update.patch # linux1394 git patches @@ -1338,6 +1342,7 @@ ApplyPatch linux-2.6-silence-acpi-blacklist.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty +ApplyPatch cx88-Fix-HVR4000-IR-keymap.patch -R ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch @@ -1371,12 +1376,12 @@ ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch #rhbz 668231 ApplyPatch linux-2.6-netconsole-deadlock.patch -# CVE-2011-1494, CVE-2011-1495 -ApplyPatch scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch - # CVE-2011-1581 ApplyPatch bonding-incorrect-tx-queue-offset.patch +ApplyPatch can-add-missing-socket-check-in-can_raw_release.patch +ApplyPatch scsi-fix-oops-in-scsi_run_queue.patch + # END OF PATCH APPLICATIONS %endif @@ -1985,6 +1990,15 @@ fi # and build. %changelog +* Mon May 09 2011 Kyle McMartin +- Update to stable review 2.6.38.6-rc1 +- Revert DRM patch duplicated in drm-radeon-update rollup. +- Revert cx88 fix in stable which has been fixed differently in the + v4l-dvb-update backport. +- Add two patches which should make it into the final 2.6.38.6 release. + - can-add-missing-socket-check-in-can_raw_release.patch + - scsi-fix-oops-in-scsi_run_queue.patch + * Mon May 09 2011 Chuck Ebbert - Enable CONFIG_FB_UDL (#634636) diff --git a/scsi-fix-oops-in-scsi_run_queue.patch b/scsi-fix-oops-in-scsi_run_queue.patch new file mode 100644 index 000000000..eb4e686e1 --- /dev/null +++ b/scsi-fix-oops-in-scsi_run_queue.patch @@ -0,0 +1,49 @@ +From 02bac892354cafaf84ca8fe657c34145bd1d1f1a Mon Sep 17 00:00:00 2001 +From: James Bottomley +Date: Sun, 1 May 2011 09:42:07 -0500 +Subject: [PATCH] [SCSI] fix oops in scsi_run_queue() + +The recent commit closing the race window in device teardown: + +commit 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b +Author: James Bottomley +Date: Fri Apr 22 10:39:59 2011 -0500 + + [SCSI] put stricter guards on queue dead checks + +is causing a potential NULL deref in scsi_run_queue() because the +q->queuedata may already be NULL by the time this function is called. +Since we shouldn't be running a queue that is being torn down, simply +add a NULL check in scsi_run_queue() to forestall this. + +Tested-by: Jim Schutt +Cc: stable@kernel.org +Signed-off-by: James Bottomley +--- + drivers/scsi/scsi_lib.c | 7 ++++++- + 1 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index fb2bb35..415fdf2 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -400,10 +400,15 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost) + static void scsi_run_queue(struct request_queue *q) + { + struct scsi_device *sdev = q->queuedata; +- struct Scsi_Host *shost = sdev->host; ++ struct Scsi_Host *shost; + LIST_HEAD(starved_list); + unsigned long flags; + ++ /* if the device is dead, sdev will be NULL, so no queue to run */ ++ if (!sdev) ++ return; ++ ++ shost = sdev->host; + if (scsi_target(sdev)->single_lun) + scsi_single_lun_run(sdev); + +-- +1.7.5.1 + diff --git a/scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch b/scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch deleted file mode 100644 index 1803cf84f..000000000 --- a/scsi-mptsas-prevent-heap-overflows-and-unchecked-reads.patch +++ /dev/null @@ -1,83 +0,0 @@ -From: Dan Rosenberg -Date: Tue, 5 Apr 2011 16:45:59 +0000 (-0400) -Subject: [SCSI] mpt2sas: prevent heap overflows and unchecked reads -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=a1f74ae82d133ebb2aabb19d181944b4e83e9960 - -[SCSI] mpt2sas: prevent heap overflows and unchecked reads - -At two points in handling device ioctls via /dev/mpt2ctl, user-supplied -length values are used to copy data from userspace into heap buffers -without bounds checking, allowing controllable heap corruption and -subsequently privilege escalation. - -Additionally, user-supplied values are used to determine the size of a -copy_to_user() as well as the offset into the buffer to be read, with no -bounds checking, allowing users to read arbitrary kernel memory. - -Signed-off-by: Dan Rosenberg -Cc: stable@kernel.org -Acked-by: Eric Moore -Signed-off-by: James Bottomley ---- - -diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c -index 1c6d2b4..d72f1f2 100644 ---- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c -+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c -@@ -688,6 +688,13 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, - goto out; - } - -+ /* Check for overflow and wraparound */ -+ if (karg.data_sge_offset * 4 > ioc->request_sz || -+ karg.data_sge_offset > (UINT_MAX / 4)) { -+ ret = -EINVAL; -+ goto out; -+ } -+ - /* copy in request message frame from user */ - if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { - printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__, -@@ -1963,7 +1970,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) - Mpi2DiagBufferPostReply_t *mpi_reply; - int rc, i; - u8 buffer_type; -- unsigned long timeleft; -+ unsigned long timeleft, request_size, copy_size; - u16 smid; - u16 ioc_status; - u8 issue_reset = 0; -@@ -1999,6 +2006,8 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) - return -ENOMEM; - } - -+ request_size = ioc->diag_buffer_sz[buffer_type]; -+ - if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { - printk(MPT2SAS_ERR_FMT "%s: either the starting_offset " - "or bytes_to_read are not 4 byte aligned\n", ioc->name, -@@ -2006,13 +2015,23 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) - return -EINVAL; - } - -+ if (karg.starting_offset > request_size) -+ return -EINVAL; -+ - diag_data = (void *)(request_data + karg.starting_offset); - dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), " - "offset(%d), sz(%d)\n", ioc->name, __func__, - diag_data, karg.starting_offset, karg.bytes_to_read)); - -+ /* Truncate data on requests that are too large */ -+ if ((diag_data + karg.bytes_to_read < diag_data) || -+ (diag_data + karg.bytes_to_read > request_data + request_size)) -+ copy_size = request_size - karg.starting_offset; -+ else -+ copy_size = karg.bytes_to_read; -+ - if (copy_to_user((void __user *)uarg->diagnostic_data, -- diag_data, karg.bytes_to_read)) { -+ diag_data, copy_size)) { - printk(MPT2SAS_ERR_FMT "%s: Unable to write " - "mpt_diag_read_buffer_t data @ %p\n", ioc->name, - __func__, diag_data); diff --git a/sources b/sources index 12ff2148e..002b7a67c 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 c8f233d1d31030eb019ab391071e65c2 patch-2.6.38.5.bz2 +786f63ba166fbcf811dae759d04d00a3 patch-2.6.38.6-rc1.bz2 From ac4b917a221984723fc1c6bc9fba758932ff4d4f Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 9 May 2011 16:15:08 -0400 Subject: [PATCH 52/99] Fix a VM bug introduced in 2.6.38.4 --- kernel.spec | 9 ++- ...kup-in-get_user_pages-only-for-mlock.patch | 78 +++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch diff --git a/kernel.spec b/kernel.spec index 43db90ea2..fe91f59db 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 25 +%global baserelease 26 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -745,6 +745,8 @@ Patch12410: scsi-fix-oops-in-scsi_run_queue.patch Patch12420: can-add-missing-socket-check-in-can_raw_release.patch +Patch12430: vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1379,8 +1381,10 @@ ApplyPatch linux-2.6-netconsole-deadlock.patch # CVE-2011-1581 ApplyPatch bonding-incorrect-tx-queue-offset.patch +# 2.6.38.6-rc1 fixes requested for final ApplyPatch can-add-missing-socket-check-in-can_raw_release.patch ApplyPatch scsi-fix-oops-in-scsi_run_queue.patch +ApplyPatch vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch # END OF PATCH APPLICATIONS @@ -1990,6 +1994,9 @@ fi # and build. %changelog +* Mon May 09 2011 Chuck Ebbert 2.6.38.6-26.rc1 +- Fix a VM bug introduced in 2.6.38.4 + * Mon May 09 2011 Kyle McMartin - Update to stable review 2.6.38.6-rc1 - Revert DRM patch duplicated in drm-radeon-update rollup. diff --git a/vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch b/vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch new file mode 100644 index 000000000..c80e93a77 --- /dev/null +++ b/vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch @@ -0,0 +1,78 @@ +From: Linus Torvalds +Date: Thu, 5 May 2011 04:30:28 +0000 (-0700) +Subject: VM: skip the stack guard page lookup in get_user_pages only for mlock +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=a1fde08c74e90accd62d4cfdbf580d2ede938fe7 + +VM: skip the stack guard page lookup in get_user_pages only for mlock + +The logic in __get_user_pages() used to skip the stack guard page lookup +whenever the caller wasn't interested in seeing what the actual page +was. But Michel Lespinasse points out that there are cases where we +don't care about the physical page itself (so 'pages' may be NULL), but +do want to make sure a page is mapped into the virtual address space. + +So using the existence of the "pages" array as an indication of whether +to look up the guard page or not isn't actually so great, and we really +should just use the FOLL_MLOCK bit. But because that bit was only set +for the VM_LOCKED case (and not all vma's necessarily have it, even for +mlock()), we couldn't do that originally. + +Fix that by moving the VM_LOCKED check deeper into the call-chain, which +actually simplifies many things. Now mlock() gets simpler, and we can +also check for FOLL_MLOCK in __get_user_pages() and the code ends up +much more straightforward. + +Reported-and-reviewed-by: Michel Lespinasse +Cc: stable@kernel.org +Signed-off-by: Linus Torvalds +--- + +diff --git a/mm/memory.c b/mm/memory.c +index 607098d4..27f4253 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1359,7 +1359,7 @@ split_fallthrough: + */ + mark_page_accessed(page); + } +- if (flags & FOLL_MLOCK) { ++ if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { + /* + * The preliminary mapping check is mainly to avoid the + * pointless overhead of lock_page on the ZERO_PAGE +@@ -1552,10 +1552,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + } + + /* +- * If we don't actually want the page itself, +- * and it's the stack guard page, just skip it. ++ * For mlock, just skip the stack guard page. + */ +- if (!pages && stack_guard_page(vma, start)) ++ if ((gup_flags & FOLL_MLOCK) && stack_guard_page(vma, start)) + goto next_page; + + do { +diff --git a/mm/mlock.c b/mm/mlock.c +index 6b55e3e..516b2c2 100644 +--- a/mm/mlock.c ++++ b/mm/mlock.c +@@ -162,7 +162,7 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, + VM_BUG_ON(end > vma->vm_end); + VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem)); + +- gup_flags = FOLL_TOUCH; ++ gup_flags = FOLL_TOUCH | FOLL_MLOCK; + /* + * We want to touch writable mappings with a write fault in order + * to break COW, except for shared mappings because these don't COW +@@ -178,9 +178,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, + if (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)) + gup_flags |= FOLL_FORCE; + +- if (vma->vm_flags & VM_LOCKED) +- gup_flags |= FOLL_MLOCK; +- + return __get_user_pages(current, mm, addr, nr_pages, gup_flags, + NULL, NULL, nonblocking); + } From 49be14f7fd347667b87c89e929469ad3282c94e8 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Tue, 10 May 2011 09:07:12 -0400 Subject: [PATCH 53/99] Linux 2.6.38.6 (no functional changes from 2.6.38.6-26.rc1) --- ...sing-socket-check-in-can_raw_release.patch | 39 ---------- kernel.spec | 22 +++--- scsi-fix-oops-in-scsi_run_queue.patch | 49 ------------ sources | 3 +- ...kup-in-get_user_pages-only-for-mlock.patch | 78 ------------------- 5 files changed, 10 insertions(+), 181 deletions(-) delete mode 100644 can-add-missing-socket-check-in-can_raw_release.patch delete mode 100644 scsi-fix-oops-in-scsi_run_queue.patch delete mode 100644 vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch diff --git a/can-add-missing-socket-check-in-can_raw_release.patch b/can-add-missing-socket-check-in-can_raw_release.patch deleted file mode 100644 index b960fd5a1..000000000 --- a/can-add-missing-socket-check-in-can_raw_release.patch +++ /dev/null @@ -1,39 +0,0 @@ -From b3be9dcd312f13563b68d0432830ef94dd3b33de Mon Sep 17 00:00:00 2001 -From: Oliver Hartkopp -Date: Wed, 20 Apr 2011 01:57:15 +0000 -Subject: [PATCH] can: add missing socket check in can/raw release - -v2: added space after 'if' according code style. - -We can get here with a NULL socket argument passed from userspace, -so we need to handle it accordingly. - -Thanks to Dave Jones pointing at this issue in net/can/bcm.c - -Signed-off-by: Oliver Hartkopp -Signed-off-by: David S. Miller ---- - net/can/raw.c | 7 ++++++- - 1 files changed, 6 insertions(+), 1 deletions(-) - -diff --git a/net/can/raw.c b/net/can/raw.c -index 883e9d7..241b2b6 100644 ---- a/net/can/raw.c -+++ b/net/can/raw.c -@@ -305,7 +305,12 @@ static int raw_init(struct sock *sk) - static int raw_release(struct socket *sock) - { - struct sock *sk = sock->sk; -- struct raw_sock *ro = raw_sk(sk); -+ struct raw_sock *ro; -+ -+ if (!sk) -+ return 0; -+ -+ ro = raw_sk(sk); - - unregister_netdevice_notifier(&ro->notifier); - --- -1.7.5.1 - diff --git a/kernel.spec b/kernel.spec index fe91f59db..10eed1360 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 26 +%global baserelease 27 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -65,7 +65,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 6 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -741,12 +741,6 @@ Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-availabl # Fix breakage of PCI network adapter names on older Dell systems Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch -Patch12410: scsi-fix-oops-in-scsi_run_queue.patch - -Patch12420: can-add-missing-socket-check-in-can_raw_release.patch - -Patch12430: vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch - %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1381,11 +1375,6 @@ ApplyPatch linux-2.6-netconsole-deadlock.patch # CVE-2011-1581 ApplyPatch bonding-incorrect-tx-queue-offset.patch -# 2.6.38.6-rc1 fixes requested for final -ApplyPatch can-add-missing-socket-check-in-can_raw_release.patch -ApplyPatch scsi-fix-oops-in-scsi_run_queue.patch -ApplyPatch vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch - # END OF PATCH APPLICATIONS %endif @@ -1994,6 +1983,13 @@ fi # and build. %changelog +* Tue May 10 2011 Chuck Ebbert +- Linux 2.6.38.6 (no functional changes from 2.6.38.6-26.rc1) +- Drop merged patches: + can-add-missing-socket-check-in-can_raw_release.patch + scsi-fix-oops-in-scsi_run_queue.patch + vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch + * Mon May 09 2011 Chuck Ebbert 2.6.38.6-26.rc1 - Fix a VM bug introduced in 2.6.38.4 diff --git a/scsi-fix-oops-in-scsi_run_queue.patch b/scsi-fix-oops-in-scsi_run_queue.patch deleted file mode 100644 index eb4e686e1..000000000 --- a/scsi-fix-oops-in-scsi_run_queue.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 02bac892354cafaf84ca8fe657c34145bd1d1f1a Mon Sep 17 00:00:00 2001 -From: James Bottomley -Date: Sun, 1 May 2011 09:42:07 -0500 -Subject: [PATCH] [SCSI] fix oops in scsi_run_queue() - -The recent commit closing the race window in device teardown: - -commit 86cbfb5607d4b81b1a993ff689bbd2addd5d3a9b -Author: James Bottomley -Date: Fri Apr 22 10:39:59 2011 -0500 - - [SCSI] put stricter guards on queue dead checks - -is causing a potential NULL deref in scsi_run_queue() because the -q->queuedata may already be NULL by the time this function is called. -Since we shouldn't be running a queue that is being torn down, simply -add a NULL check in scsi_run_queue() to forestall this. - -Tested-by: Jim Schutt -Cc: stable@kernel.org -Signed-off-by: James Bottomley ---- - drivers/scsi/scsi_lib.c | 7 ++++++- - 1 files changed, 6 insertions(+), 1 deletions(-) - -diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c -index fb2bb35..415fdf2 100644 ---- a/drivers/scsi/scsi_lib.c -+++ b/drivers/scsi/scsi_lib.c -@@ -400,10 +400,15 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost) - static void scsi_run_queue(struct request_queue *q) - { - struct scsi_device *sdev = q->queuedata; -- struct Scsi_Host *shost = sdev->host; -+ struct Scsi_Host *shost; - LIST_HEAD(starved_list); - unsigned long flags; - -+ /* if the device is dead, sdev will be NULL, so no queue to run */ -+ if (!sdev) -+ return; -+ -+ shost = sdev->host; - if (scsi_target(sdev)->single_lun) - scsi_single_lun_run(sdev); - --- -1.7.5.1 - diff --git a/sources b/sources index 002b7a67c..cd4a5e33c 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -c8f233d1d31030eb019ab391071e65c2 patch-2.6.38.5.bz2 -786f63ba166fbcf811dae759d04d00a3 patch-2.6.38.6-rc1.bz2 +527fab8162c682ad849eb21fc30d28ef patch-2.6.38.6.bz2 diff --git a/vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch b/vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch deleted file mode 100644 index c80e93a77..000000000 --- a/vm-skip-the-stack-guard-page-lookup-in-get_user_pages-only-for-mlock.patch +++ /dev/null @@ -1,78 +0,0 @@ -From: Linus Torvalds -Date: Thu, 5 May 2011 04:30:28 +0000 (-0700) -Subject: VM: skip the stack guard page lookup in get_user_pages only for mlock -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=a1fde08c74e90accd62d4cfdbf580d2ede938fe7 - -VM: skip the stack guard page lookup in get_user_pages only for mlock - -The logic in __get_user_pages() used to skip the stack guard page lookup -whenever the caller wasn't interested in seeing what the actual page -was. But Michel Lespinasse points out that there are cases where we -don't care about the physical page itself (so 'pages' may be NULL), but -do want to make sure a page is mapped into the virtual address space. - -So using the existence of the "pages" array as an indication of whether -to look up the guard page or not isn't actually so great, and we really -should just use the FOLL_MLOCK bit. But because that bit was only set -for the VM_LOCKED case (and not all vma's necessarily have it, even for -mlock()), we couldn't do that originally. - -Fix that by moving the VM_LOCKED check deeper into the call-chain, which -actually simplifies many things. Now mlock() gets simpler, and we can -also check for FOLL_MLOCK in __get_user_pages() and the code ends up -much more straightforward. - -Reported-and-reviewed-by: Michel Lespinasse -Cc: stable@kernel.org -Signed-off-by: Linus Torvalds ---- - -diff --git a/mm/memory.c b/mm/memory.c -index 607098d4..27f4253 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -1359,7 +1359,7 @@ split_fallthrough: - */ - mark_page_accessed(page); - } -- if (flags & FOLL_MLOCK) { -+ if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) { - /* - * The preliminary mapping check is mainly to avoid the - * pointless overhead of lock_page on the ZERO_PAGE -@@ -1552,10 +1552,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, - } - - /* -- * If we don't actually want the page itself, -- * and it's the stack guard page, just skip it. -+ * For mlock, just skip the stack guard page. - */ -- if (!pages && stack_guard_page(vma, start)) -+ if ((gup_flags & FOLL_MLOCK) && stack_guard_page(vma, start)) - goto next_page; - - do { -diff --git a/mm/mlock.c b/mm/mlock.c -index 6b55e3e..516b2c2 100644 ---- a/mm/mlock.c -+++ b/mm/mlock.c -@@ -162,7 +162,7 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, - VM_BUG_ON(end > vma->vm_end); - VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem)); - -- gup_flags = FOLL_TOUCH; -+ gup_flags = FOLL_TOUCH | FOLL_MLOCK; - /* - * We want to touch writable mappings with a write fault in order - * to break COW, except for shared mappings because these don't COW -@@ -178,9 +178,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, - if (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)) - gup_flags |= FOLL_FORCE; - -- if (vma->vm_flags & VM_LOCKED) -- gup_flags |= FOLL_MLOCK; -- - return __get_user_pages(current, mm, addr, nr_pages, gup_flags, - NULL, NULL, nonblocking); - } From 34f3a6f6cf21208e81be1c91e980a53b9d06c331 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 10 May 2011 11:13:35 -0400 Subject: [PATCH 54/99] [sgruszka@] iwlwifi: add {ack,plpc}_check module parameters (#666646) --- ...dd-_ack_plpc_check-module-parameters.patch | 96 +++++++++++++++++++ kernel.spec | 9 ++ 2 files changed, 105 insertions(+) create mode 100644 iwlwifi-add-_ack_plpc_check-module-parameters.patch diff --git a/iwlwifi-add-_ack_plpc_check-module-parameters.patch b/iwlwifi-add-_ack_plpc_check-module-parameters.patch new file mode 100644 index 000000000..a6211b51e --- /dev/null +++ b/iwlwifi-add-_ack_plpc_check-module-parameters.patch @@ -0,0 +1,96 @@ +From sgruszka@redhat.com Mon May 9 15:27:33 2011 +From: Stanislaw Gruszka +To: kernel@lists.fedoraproject.org, stable@kernel.org +Cc: Kyle McMartin , + Stanislaw Gruszka +Subject: [PATCH 2.6.38] iwlwifi: add {ack,plpc}_check module parameters +Date: Mon, 9 May 2011 21:27:30 +0200 +Message-Id: <1304969250-27725-1-git-send-email-sgruszka@redhat.com> + +commit b7977ffaab5187ad75edaf04ac854615cea93828 upstream. + +Add module ack_check, and plcp_check parameters. Ack_check is disabled +by default since is proved that check ack health can cause troubles. +Plcp_check is enabled by default. + +This prevent connection hangs with "low ack count detected" messages. + +Resolves: +https://bugzilla.redhat.com/show_bug.cgi?id=666646 + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 + + drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ + drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ + drivers/net/wireless/iwlwifi/iwl-rx.c | 8 ++++++-- + 4 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +index 3dee87e..d9c87b3 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +@@ -604,6 +604,7 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, + struct iwl_mod_params iwlagn_mod_params = { + .amsdu_size_8K = 1, + .restart_fw = 1, ++ .plcp_check = true, + /* the rest are 0 by default */ + }; + +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c +index 35239f0..be07643 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -4586,3 +4586,9 @@ MODULE_PARM_DESC(antenna_coupling, + module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO); + MODULE_PARM_DESC(bt_ch_inhibition, + "Disable BT channel inhibition (default: enable)"); ++ ++module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO); ++MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); ++ ++module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO); ++MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); +diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h +index a347437..5c0d5f7 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-core.h ++++ b/drivers/net/wireless/iwlwifi/iwl-core.h +@@ -263,6 +263,8 @@ struct iwl_mod_params { + int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ + int antenna; /* def: 0 = both antennas (use diversity) */ + int restart_fw; /* def: 1 = restart firmware */ ++ bool plcp_check; /* def: true = enable plcp health check */ ++ bool ack_check; /* def: false = disable ack health check */ + }; + + /* +diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c +index 87a6fd8..b707617 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-rx.c ++++ b/drivers/net/wireless/iwlwifi/iwl-rx.c +@@ -234,10 +234,13 @@ EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); + void iwl_recover_from_statistics(struct iwl_priv *priv, + struct iwl_rx_packet *pkt) + { ++ const struct iwl_mod_params *mod_params = priv->cfg->mod_params; ++ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + if (iwl_is_any_associated(priv)) { +- if (priv->cfg->ops->lib->check_ack_health) { ++ if (mod_params->ack_check && ++ priv->cfg->ops->lib->check_ack_health) { + if (!priv->cfg->ops->lib->check_ack_health( + priv, pkt)) { + /* +@@ -250,7 +253,8 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, + return; + } + } +- if (priv->cfg->ops->lib->check_plcp_health) { ++ if (mod_params->plcp_check && ++ priv->cfg->ops->lib->check_plcp_health) { + if (!priv->cfg->ops->lib->check_plcp_health( + priv, pkt)) { + /* diff --git a/kernel.spec b/kernel.spec index 10eed1360..2bba6288d 100644 --- a/kernel.spec +++ b/kernel.spec @@ -741,6 +741,9 @@ Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-availabl # Fix breakage of PCI network adapter names on older Dell systems Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch +# iwlwifi: add {ack,plpc}_check module parameters (#666646) +Patch12405: iwlwifi-add-_ack_plpc_check-module-parameters.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1375,6 +1378,9 @@ ApplyPatch linux-2.6-netconsole-deadlock.patch # CVE-2011-1581 ApplyPatch bonding-incorrect-tx-queue-offset.patch +# iwlwifi: add {ack,plpc}_check module parameters (#666646) queued for stable +ApplyPatch iwlwifi-add-_ack_plpc_check-module-parameters.patch + # END OF PATCH APPLICATIONS %endif @@ -1983,6 +1989,9 @@ fi # and build. %changelog +* Tue May 10 2011 Kyle McMartin +- [sgruszka@] iwlwifi: add {ack,plpc}_check module parameters (#666646) + * Tue May 10 2011 Chuck Ebbert - Linux 2.6.38.6 (no functional changes from 2.6.38.6-26.rc1) - Drop merged patches: From 8d4bec9c02e1dc61fb0d0130dc48f21c11934649 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 11 May 2011 09:13:50 -0400 Subject: [PATCH 55/99] Fix Intel IPS driver so it doesn't run continuously (#703511) --- ...e-interruptible-waits-in-ips-monitor.patch | 30 +++++++++++++++++++ kernel.spec | 9 ++++++ 2 files changed, 39 insertions(+) create mode 100644 ips-use-interruptible-waits-in-ips-monitor.patch diff --git a/ips-use-interruptible-waits-in-ips-monitor.patch b/ips-use-interruptible-waits-in-ips-monitor.patch new file mode 100644 index 000000000..dbea1a1a0 --- /dev/null +++ b/ips-use-interruptible-waits-in-ips-monitor.patch @@ -0,0 +1,30 @@ +From: Jesse Barnes +Date: Mon, 28 Mar 2011 10:36:30 +0000 (-0400) +Subject: ips: use interruptible waits in ips-monitor +X-Git-Tag: v2.6.39-rc1~20^2^2~1 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=a3424216e4935221fdaa5ca3c26e024f11297164 + +ips: use interruptible waits in ips-monitor + +This is what I intended to do since: + 1) the driver handles variable waits just fine, and + 2) interruptible waits aren't reported as load in the load avg. + +Reported-and-tested-by: Andreas Hartmann +Signed-off-by: Jesse Barnes +Signed-off-by: Matthew Garrett +--- + +diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c +index 1294a39..85c8ad4 100644 +--- a/drivers/platform/x86/intel_ips.c ++++ b/drivers/platform/x86/intel_ips.c +@@ -1111,7 +1111,7 @@ static int ips_monitor(void *data) + last_msecs = jiffies_to_msecs(jiffies); + expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD); + +- __set_current_state(TASK_UNINTERRUPTIBLE); ++ __set_current_state(TASK_INTERRUPTIBLE); + mod_timer(&timer, expire); + schedule(); + diff --git a/kernel.spec b/kernel.spec index 2bba6288d..85c05951e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -744,6 +744,9 @@ Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patc # iwlwifi: add {ack,plpc}_check module parameters (#666646) Patch12405: iwlwifi-add-_ack_plpc_check-module-parameters.patch +# intel_ips driver bug (#703511) causes cooling fan to run +Patch12406: ips-use-interruptible-waits-in-ips-monitor.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1381,6 +1384,9 @@ ApplyPatch bonding-incorrect-tx-queue-offset.patch # iwlwifi: add {ack,plpc}_check module parameters (#666646) queued for stable ApplyPatch iwlwifi-add-_ack_plpc_check-module-parameters.patch +# intel_ips driver bug (#703511) causes cooling fan to run +ApplyPatch ips-use-interruptible-waits-in-ips-monitor.patch + # END OF PATCH APPLICATIONS %endif @@ -1989,6 +1995,9 @@ fi # and build. %changelog +* Wed May 11 2011 Chuck Ebbert +- Fix Intel IPS driver so it doesn't run continuously (#703511) + * Tue May 10 2011 Kyle McMartin - [sgruszka@] iwlwifi: add {ack,plpc}_check module parameters (#666646) From 3c5f6df32d87d756243c2a5bb50db89a8643b046 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Fri, 13 May 2011 08:27:35 -0400 Subject: [PATCH 56/99] fix a deadlock in scsi_dh_hp_sw --- kernel.spec | 8 +++++ ..._sw-fix-deadlock-in-start_stop_endio.patch | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch diff --git a/kernel.spec b/kernel.spec index 85c05951e..5e8fa1100 100644 --- a/kernel.spec +++ b/kernel.spec @@ -747,6 +747,8 @@ Patch12405: iwlwifi-add-_ack_plpc_check-module-parameters.patch # intel_ips driver bug (#703511) causes cooling fan to run Patch12406: ips-use-interruptible-waits-in-ips-monitor.patch +Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1387,6 +1389,8 @@ ApplyPatch iwlwifi-add-_ack_plpc_check-module-parameters.patch # intel_ips driver bug (#703511) causes cooling fan to run ApplyPatch ips-use-interruptible-waits-in-ips-monitor.patch +ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch + # END OF PATCH APPLICATIONS %endif @@ -1995,6 +1999,10 @@ fi # and build. %changelog +* Fri May 13 2011 Kyle McMartin +- [fabbione@] Fix a deadlock when using hp_sw with an HP san. + (7a1e9d82 upstream) + * Wed May 11 2011 Chuck Ebbert - Fix Intel IPS driver so it doesn't run continuously (#703511) diff --git a/scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch b/scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch new file mode 100644 index 000000000..faded334b --- /dev/null +++ b/scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch @@ -0,0 +1,32 @@ +From 7a1e9d829f8bd821466c5ea834ad6f378740d2be Mon Sep 17 00:00:00 2001 +From: Mike Snitzer +Date: Tue, 25 Jan 2011 11:52:17 -0500 +Subject: [SCSI] scsi_dh_hp_sw: fix deadlock in start_stop_endio + +The use of blk_execute_rq_nowait() implies __blk_put_request() is needed +in start_stop_endio() rather than blk_put_request() -- +blk_finish_request() is called with queue lock already held. + +Signed-off-by: Mike Snitzer +Signed-off-by: James Bottomley +--- + drivers/scsi/device_handler/scsi_dh_hp_sw.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c +index e391664..d0363c8 100644 +--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c ++++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c +@@ -225,7 +225,8 @@ static void start_stop_endio(struct request *req, int error) + } + } + done: +- blk_put_request(req); ++ req->end_io_data = NULL; ++ __blk_put_request(req->q, req); + if (h->callback_fn) { + h->callback_fn(h->callback_data, err); + h->callback_fn = h->callback_data = NULL; +-- +1.7.5.1 + From 6c43c19fb88693051060bd5a797747ed83082c85 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sun, 15 May 2011 12:51:20 -0400 Subject: [PATCH 57/99] tag and build also drop pre-2.6.36 history, since it's more than 8 months old and was no longer relevant. (the only still-relevant bits are config setting justification, and that can easily be found by git blame.) --- kernel.spec | 579 +--------------------------------------------------- 1 file changed, 1 insertion(+), 578 deletions(-) diff --git a/kernel.spec b/kernel.spec index 5e8fa1100..4b6af4d27 100644 --- a/kernel.spec +++ b/kernel.spec @@ -1999,7 +1999,7 @@ fi # and build. %changelog -* Fri May 13 2011 Kyle McMartin +* Fri May 13 2011 Kyle McMartin 2.6.38.6-28 - [fabbione@] Fix a deadlock when using hp_sw with an HP san. (7a1e9d82 upstream) @@ -2616,583 +2616,6 @@ fi * Wed Oct 20 2010 Chuck Ebbert 2.6.36-1 - Linux 2.6.36 -* Wed Oct 20 2010 Matthew Garrett 2.6.36-0.42.rc8.git5 -- runtime_pm_fixups.patch: should fix this on Thinkpads - -* Tue Oct 19 2010 Chuck Ebbert 2.6.36-0.41.rc8.git5 -- Linux 2.6.36-rc8-git5 -- Update PCI _CRS fixes - -* Mon Oct 18 2010 Kyle McMartin 2.6.36-0.40.rc8.git0 -- Backport xHCI suspend/resume code from linux-next. - -* Mon Oct 18 2010 Kyle McMartin -- ima: Default it to off, pass ima=on to enable. Reduce impact of the option - when disabled. - -* Mon Oct 18 2010 Kyle McMartin -- Quirk to disable DMAR with Ricoh card reader/firewire. (rhbz#605888) - -* Fri Oct 15 2010 Kyle McMartin -- Switched to pci=use_crs by default (it should have been fixed since - cebbert sucked in the patches anyway.) - -* Fri Oct 15 2010 Kyle McMartin -- backport pnpacpi-cope-with-invalid-device-ids from linux-next. - (rhbz#641468) - -* Fri Oct 15 2010 Kyle McMartin 2.6.36-0.39.rc8.git0 -- Linux 2.6.36-rc8. - -* Thu Oct 14 2010 Kyle McMartin 2.6.36-0.38.rc7.git5 -- Linux 2.6.36-rc7-git5 -- Disable runtime PM until it can be poked at. - -* Tue Oct 12 2010 Kyle McMartin 2.6.36-0.36.rc7.git3 -- Linux 2.6.36-rc7-git3 -- Drop fix-oldnoconfig-to-dtrt.patch, nonintconfig patches are upstream! - -* Mon Oct 11 2010 Matthew Garrett 2.6.36-0.35.rc7.git1 -- linux-2.6-enable-more-pci-autosuspend.patch: Enable more PCI autosuspend - -* Wed Oct 06 2010 Kyle McMartin 2.6.36-0.35.rc7.git0 -- Linux 2.6.36-rc7 upstream. - -* Wed Oct 06 2010 Dave Jones -- Another day, another rcu_dereference warning. (#640673) - -* Tue Oct 05 2010 Kyle McMartin 2.6.36-0.34.rc6.git3 -- Linux 2.6.36-rc6-git3 -- Drop intel_ips patches merged upstream. - -* Sun Oct 03 2010 Kyle McMartin 2.6.36-0.32.rc6.git2 -- Enable printk.time by default for more useful logs. - -* Sat Oct 02 2010 Kyle McMartin 2.6.36-0.31.rc6.git2 -- Linux 2.6.36-rc6-git2 - -* Thu Sep 30 2010 Dave Jones -- silence another rcu_reference warning - -* Thu Sep 30 2010 Kyle McMartin 2.6.36-0.30.rc6 -- Collection of patches to make intel_ips work properly. - -* Wed Sep 29 2010 Dave Jones -- Add back an old hack to make an SDV e1000e variant work. - -* Wed Sep 29 2010 Dave Jones -- Enable IB700 watchdog (used by qemu/kvm). (#637152) - -* Tue Sep 28 2010 Kyle McMartin 2.6.36-0.28.rc6 -- Linux 2.6.36-rc6 - -* Fri Sep 24 2010 Chuck Ebbert 2.6.36-0.27.rc5.git6 -- Linux 2.6.36-rc5-git6 - -* Thu Sep 23 2010 Kyle McMartin -- Bump x86 NR_CPUS to 64. (Still 512/256 on x86_64.) - -* Thu Sep 23 2010 Chuck Ebbert 2.6.36-0.26.rc5.git4 -- Linux 2.6.36-rc5-git4 -- Drop merged patches: - fix-icebp-breakpoints.patch - linux-2.6.35.4-virtio_console-fix-poll.patch -- Add patches to fix problems with PCI _CRS - -* Thu Sep 23 2010 Kyle McMartin 2.6.36-0.25.rc5 -- Add s390 vdso AFTER_LINK to Roland's linux-2.6-makefile-after_link.patch - -* Thu Sep 23 2010 Kyle McMartin -- Snipe ACPI patch from mjg59 to fix battery levels on some laptops. - -* Tue Sep 21 2010 Kyle McMartin -- Add new btusb ids for MacBookPro from wwoods@. - -* Mon Sep 20 2010 Chuck Ebbert - 2.6.36-0.24.rc5 -- Linux 2.6.36-rc5 - -* Sun Sep 19 2010 Chuck Ebbert - 2.6.36-0.23.rc4.git4 -- Linux 2.6.36-rc4-git4 -- Drop alsa-fix-substream-proc-status-read.patch, now merged. - -* Fri Sep 17 2010 Matthew Garrett -- linux-2.6-bluetooth-autosuspend.patch - linux-2.6-uvc-autosuspend.patch - linux-2.6-qcserial-autosuspend.patch - linux-2.6-usb-pci-autosuspend.patch - Get some more devices into USB - autosuspend by default, and then put unused USB controllers to sleep - -* Thu Sep 16 2010 Hans de Goede -- Small fix to virtio_console poll fix from upstream review - -* Wed Sep 15 2010 Hans de Goede -- virtio_console: Fix poll/select blocking even though there is data to read - -* Wed Sep 15 2010 Chuck Ebbert - 2.6.36-0.22.rc4.git2 -- Linux 2.6.36-rc4-git2 -- Fix up add-appleir-usb-driver.patch after HID core changes. - -* Mon Sep 13 2010 Chuck Ebbert - 2.6.36-0.21.rc4.git1 -- Linux 2.6.36-rc4-git1 -- Add preliminary support for Wacom Bamboo pen and touch devices. -- Require python-devel and perl(ExtUtils::Embed) when building perf package (#632942) - -* Sat Sep 11 2010 Chuck Ebbert - 2.6.36-0.20.rc3.git4 -- Linux 2.6.36-rc3-git4 -- Drop revert-drm-i915-enable-rc6-on-ironlake.patch, now merged - -* Fri Sep 10 2010 Bastien Nocera - 2.6.36-0.19.rc3.git1 -- Update AppleIR patch to work, and support the enter key on - newer remotes - -* Wed Sep 08 2010 Kyle McMartin -- Enable GPIO_SYSFS. (#631958) - -* Wed Sep 08 2010 Kyle McMartin -- Make pci=use_crs a compile-time config option we can switch the default - value of easily. - -* Wed Sep 08 2010 Kyle McMartin 2.6.36-0.18.rc3.git1 -- 2.6.36-rc3-git1 -- Set CONFIG_CRYPTO_MANAGER_DISABLE_TESTS for nodebug, and unset for debug. - Which seems like the sensible thing to do given the Kconfig default is y. - -* Tue Sep 07 2010 Dave Jones -- Disable hung task checker, it only ever causes false positives. (#630777) - -* Tue Sep 07 2010 Kyle McMartin 2.6.36-0.17.rc3.git0 -- Revert ce171780 which breaks my graphics on resume. - (drm/i915: Enable RC6 on Ironlake.) - -* Fri Sep 03 2010 Kyle McMartin -- Restore AppleIR USB driver which got lost between F-13 and now. - -* Fri Sep 03 2010 Dave Jones 2.6.36-0.16.rc3.git0 -- exec-randomization: brk away from exec rand area (Kees Cook) - -* Fri Sep 03 2010 Dave Jones -- Remove the execshield boot parameter. - Based on a patch from Kees Cook - -* Thu Sep 02 2010 Chuck Ebbert - 2.6.36-0.15.rc3.git0 -- Add patch from ALSA mailing list to try to fix bug #628404 -- tpm-fix-stall-on-boot.patch: attempt to fix stalls during boot (#530393) - -* Wed Sep 01 2010 Kyle McMartin - 2.6.36-0.14.rc3.git0 -- Fix icebp breakpoints, patch from Frederic Weisbecker. - (https://bugzilla.kernel.org/show_bug.cgi?id=16315#c26) - -* Wed Sep 01 2010 Kyle McMartin - 2.6.36-0.13.rc3.git0 -- Swap back to roland's auto-updated utrace patches. - -* Mon Aug 30 2010 Kyle McMartin - 2.6.36-0.12.rc3.git0 -- Linux 2.6.36-rc3 - -* Sun Aug 29 2010 Chuck Ebbert - 2.6.36-0.11.rc2.git5 -- Linux 2.6.36-rc2-git5 - -* Wed Aug 25 2010 Chuck Ebbert - 2.6.36-0.10.rc2.git4 -- Linux 2.6.36-rc2-git4 - -* Tue Aug 24 2010 Chuck Ebbert - 2.6.36-0.9.rc2.git3 -- Linux 2.6.36-rc2-git3 - -* Mon Aug 23 2010 Roland McGrath - 2.6.36-0.8.rc2.git0 -- utrace update - -* Sun Aug 22 2010 Chuck Ebbert - 2.6.36-0.7.rc2.git0 -- Linux 2.6.36-rc2 - -* Sun Aug 22 2010 Chuck Ebbert - 2.6.36-0.7.rc1.git4 -- Linux 2.6.36-rc1-git4 -- Fix context in linux-2.6-i386-nx-emulation.patch - -* Sat Aug 21 2010 Chuck Ebbert - 2.6.36-0.6.rc1.git3 -- Drop utrace patch that causes hang on boot. - -* Fri Aug 20 2010 Chuck Ebbert - 2.6.36-0.5.rc1.git3 -- Linux 2.6.36-rc1-git3 -- Drop x86-cpu-fix-regression-in-amd-errata-checking-code.patch, now merged. - -* Thu Aug 19 2010 Kyle McMartin - 2.6.36-0.4.rc1.git1 -- Run oldnoconfig on the configs during make prep. -- Make the fix oldnoconfig patch a one liner. - -* Wed Aug 18 2010 Chuck Ebbert - 2.6.36-0.3.rc1.git1 -- Fix hangs on boot with some AMD processors - (x86-cpu-fix-regression-in-amd-errata-checking-code.patch) -- Drop unused ssb_check_for_sprom.patch - -* Wed Aug 18 2010 Dave Jones -- systemd is dependant upon autofs, so build it in instead of modular. - -* Wed Aug 18 2010 Chuck Ebbert -- Linux 2.6.36-rc1-git1 - -* Wed Aug 18 2010 Kyle McMartin - 2.6.36-0.2.rc1.git0 -- Link perf against libnewt for TUI support. - -* Tue Aug 17 2010 Kyle McMartin - 2.6.36-0.1.rc1.git0 -- Fix 'oldnoconfig' to do what nonint_loose_oldconfig did. - -* Tue Aug 17 2010 Kyle McMartin -- explicitly set KERNEL_GZIP - -* Tue Aug 17 2010 Kyle McMartin -- Linux 2.6.36-rc1 - -* Tue Aug 17 2010 Kyle McMartin -- Prevent scripts/setlocalversion from mucking with our version - numbers. - -* Wed Aug 04 2010 Kyle McMartin -- Disable %%released_kernel. -- This is properly 2.6.36-0.git1, unlike the last commit. Had to make - a mistake sometime, I'm glad it was early. - -* Wed Aug 04 2010 Kyle McMartin -- Linux 2.6.35-git1, beginning of rawhide for 2.6.36... - -* Sun Aug 01 2010 Dave Jones -- Linux 2.6.35 - -* Sun Aug 01 2010 Dave Jones -- 2.6.35-rc6-git6 - -* Fri Jul 30 2010 Jarod Wilson -- lirc staging update -- update kworld patch to one committed upstream -- can't believe how much nicer dist-git is than dist-cvs -- patch memory leaks in mceusb and imon drivers - -* Fri Jul 30 2010 Dave Jones -- Enable PPS (#619392) - -* Thu Jul 29 2010 Dave Jones -- 2.6.35-rc6-git5 - -* Mon Jul 27 2010 Kyle McMartin -- Patch from linville to only use the country code to set band limits. - (Fixes Apple Airport base stations from limiting you from associating - with other channels.) - -* Fri Jul 23 2010 Chuck Ebbert 2.6.35-0.56.rc6.git1 -- Linux 2.6.35-rc6-git1 - -* Thu Jul 22 2010 Dave Jones -- 2.6.35-rc6 - -* Thu Jul 22 2010 Ben Skeggsb -- drm-nouveau-updates: bring back, most patches *weren't* upstream yet, - they're queued for 2.6.36. - -* Wed Jul 21 2010 Chuck Ebbert 2.6.35-0.53.rc5.git7 -- Linux 2.6.35-rc5-git7 - -* Wed Jul 21 2010 Dave Jones -- Remove the %%verify (no mtime) on kernel-devel's files. - If they got modified, they should fail rpm verify. - -* Wed Jul 21 2010 Dave Jones -- Linux 2.6.35-rc5-git6 -- Removed drm-nouveau-updates.patch (upstreamed) - -* Mon Jul 19 2010 Chuck Ebbert -- Linux 2.6.35-rc5-git4 - -* Mon Jul 19 2010 Jarod Wilson 2.6.35-0.49.rc5.git2 -- Fix from Kyle for input_set_key oops introduced by ir-core patches (#615707) -- Update lirc-staging patches to match what's about to be submitted upstream, - complete with updated copy_from_user overflow check fixages - -* Sun Jul 18 2010 Chuck Ebbert 2.6.35-0.47.rc5.git2 -- Linux 2.6.35-rc5-git2 - -* Sun Jul 18 2010 Chuck Ebbert -- lirc-staging-2.6.36-fixes.patch: Fix up buffer size checking in - lirc code, found by CONFIG_DEBUG_STRICT_USER_COPY_CHECKS - -* Sun Jul 18 2010 Hans de Goede -- Add support for dynamic menu controls to the uvcvideo driver (#576023) - -* Sun Jul 18 2010 Jarod Wilson 2.6.35-0.44.rc5.git1 -- Oops, minor oversight when moving lirc bits into staging resulted - in the modules themselves not getting built. Fix that. - -* Fri Jul 16 2010 Dave Jones -- Limit some alsa spew that the nuforce udac makes happen a lot. - -* Fri Jul 16 2010 Jarod Wilson 2.6.35-0.41.rc5.git1 -- Pull in ir-core update from v4l/dvb staging for 2.6.36, which includes - new in-kernel lirc_dev and ir-core mceusb driver -- Move not-yet-merged/ported lirc bits to drivers/staging/, patch to be - sent upstream for 2.6.36 staging tree RSN - -* Thu Jul 15 2010 Chuck Ebbert 2.6.35-0.40.rc5.git1 -- Replace pci-acpi-disable-aspm-if-no-osc.patch with - updated version from F-13 - -* Thu Jul 15 2010 Chuck Ebbert -- Linux 2.6.35-rc5-git1 - -* Tue Jul 13 2010 Chuck Ebbert -- Linux 2.6.35-rc5 - -* Tue Jul 13 2010 Ben Skeggs -- nouveau: miscellanous fixes - -* Mon Jul 12 2010 Dave Jones -- 2.6.35-rc4-git5 - -* Mon Jul 12 2010 Dave Jones -- Remove a bunch of x86 options from config files that get set - automatically, and can't be overridden. - -* Fri Jul 9 2010 Roland McGrath -- Split execshield into two patches. - -* Thu Jul 08 2010 Chuck Ebbert 2.6.35-0.31.rc4.git4 -- Linux 2.6.35-rc4-git4 - -* Thu Jul 8 2010 Roland McGrath -- Remove exec-shield=2 setting, some other cruft from execshield. - -* Wed Jul 7 2010 Roland McGrath 2.6.35-0.29.rc4.git0.fc14 -- Revamp perf packaging. - -* Wed Jul 07 2010 Chuck Ebbert -- pci-acpi-disable-aspm-if-no-osc.patch, pci-aspm-dont-enable-too-early.patch - PCI layer fixes for problems with hardware that doesn't support ASPM. - -* Wed Jul 07 2010 Ben Skeggs -- nouveau: bring in nouveau upstream - -* Mon Jul 05 2010 Dave Jones -- 2.6.35-rc4 - -* Fri Jul 02 2010 Dave Jones -- 2.6.35-rc3-git7 - dropped: i915-fix-crt-hotplug-regression.patch (upstream) - dropped: drm-i915-fix-edp-panels.patch (upstream) - -* Fri Jul 02 2010 Dave Jones -- 2.6.35-rc3-git6 - -* Thu Jul 01 2010 Dave Jones -- Add a patch to debug an infinite loop warning from acpi. - -* Thu Jul 01 2010 Dave Jones -- 2.6.35-rc3-git5 - -* Thu Jul 01 2010 Chuck Ebbert -- Copy fix for BZ#220892 from F-13. - -* Wed Jun 30 2010 Kyle McMartin 2.6.35-0.19.rc3.git4 -- 2.6.35-rc3-git4 - -* Tue Jun 29 2010 Chuck Ebbert -- Disable Intel Moorestown support -- it breaks PC keyboard controllers. - -* Tue Jun 29 2010 Dave Jones -- Building external modules requires perl. (#608525) - -* Tue Jun 29 2010 Kyle McMartin 2.6.35-0.15.rc3.git3 -- 2.6.35-rc3-git3 -- i915-fix-crt-hotplug-regression.patch: attempt to solve the gm45 hotplug - irq storm. - -* Mon Jun 28 2010 Chuck Ebbert -- ppc64: enable active memory sharing and DLPAR memory remove (#607175) - -* Mon Jun 28 2010 Dave Jones -- 2.6.35-rc3-git2 - -* Mon Jun 28 2010 Dave Jones -- 2.6.35-rc3-git1 - -* Mon Jun 28 2010 Dave Airlie -- drm-i915-fix-edp-panels.patch: update to newer version - -* Fri Jun 25 2010 Kyle McMartin -- drm-i915-fix-edp-panels.patch: copy from rawhide. - -* Wed Jun 23 2010 Eric Sandeen -- Fix ext4 freeze deadlock (#607245) - -* Wed Jun 23 2010 Kyle McMartin -- Override generic's CONFIG_HZ_1000 on s390. - -* Tue Jun 22 2010 Dave Jones -- Fix localhost networking. - -* Tue Jun 22 2010 Kyle McMartin 2.6.35-0.1.rc3.git0 -- Putting the raw back into rawhide... Yeehaw. -- 2.6.35-rc3 -- Drop a tonne of patches that were merged upstream, or were backports. -- Rebase execshield, utrace. -- Fix up a bunch of rejects, build failures. -- Fix up lirc to build with strict copy_from_user checking. - -* Mon Jun 21 2010 Dave Jones -- Disable workaround for obscure SMP pentium pro errata. - I miss the 1990s too, but it's time to move on. - If anyone actually needs this it would be better done using - the apply_alternatives infrastructure. - -* Mon Jun 21 2010 Kyle McMartin 2.6.34-45 -- drm-revert-drm-fbdev-rework-output-polling-to-be-back-in-core.patch - Revert eb1f8e4f, bisected by Nicolas Kaiser. Thanks! (rhbz#599190) - (If this works, will try to root-cause.) -- rebase previous patch on top of above reversion - -* Mon Jun 21 2010 Kyle McMartin 2.6.34-44 -- revert-drm-kms-toggle-poll-around-switcheroo.patch (rhbz#599190) - -* Thu Jun 17 2010 Kyle McMartin 2.6.34-43 -- Suck in patch from Dave Miller in 2.6.35 to add async hash testing, - hopefully fixes error from previous commit. (But making it modular - is still a good idea.) - -* Thu Jun 17 2010 Kyle McMartin -- make ghash-clmulni modular to get rid of early boot noise (rhbz#586954) - (not a /fix/ but it should at least quiet boot down a bit if you have - the cpu support) - -* Wed Jun 16 2010 Kyle McMartin 2.6.34-40 -- Snag some more DRM commits into drm-next.patch that I missed the first - time. -- Fix up radeon_pm toggle to work with the upstream code. - -* Tue Jun 15 2010 Prarit Bhargava -- Turn off CONFIG_I2O on x86. - It is broken on 64-bit address spaces (i686/PAE, x86_64), and frankly, I'm - having trouble finding anyone who actually uses it. - -* Tue Jun 15 2010 Kyle McMartin 2.6.34-38 -- Fix build by nuking superfluous "%%{expand" which was missing a - trailing '}'. You may now reward me with an array of alcoholic - beverages, I so richly deserve for spending roughly a full - day staring at the diff of the spec. - -* Mon Jun 14 2010 Kyle McMartin 2.6.34-37 -- btrfs ACL fixes from CVE-2010-2071. - -* Sun Jun 13 2010 Kyle McMartin 2.6.34-36 -- remunge and reapply hdpvr-ir-enable - -* Sun Jun 13 2010 Kyle McMartin 2.6.34-35 -- mac80211/iwlwifi fix connections to some APs (rhbz#558002) - patches from sgruszka@. - -* Sun Jun 13 2010 Kyle McMartin 2.6.34-34 -- Provide a knob to enable radeon_pm to allow users to test - that functionality. Add radeon.pm=1 to your kernel cmdline - in order to enable it. (It still defaults to off though.) - -* Sun Jun 13 2010 Kyle McMartin 2.6.34-33 -- Update drm-next to include fixes since 2.6.35-rc1. - -* Fri Jun 11 2010 Justin M. Forbes -- Disable xsave for so that kernel will boot on ancient EC2 hosts. - -* Wed Jun 09 2010 John W. Linville -- Disable rt20xx and rt35xx chipset support in rt2800 drivers (#570869) - -* Wed Jun 09 2010 David Woodhouse -- Include PHY modules in modules.networking (#602155) - -* Tue Jun 08 2010 Dave Jones -- Remove useless -kdump kernel support - -* Tue Jun 08 2010 Dave Jones -- Remove ia64 ata quirk which had no explanation, and still - isn't upstream. No-one cares. - -* Tue Jun 08 2010 Dave Jones -- Drop linux-2.6-vio-modalias.patch - Two years should have been long enough to get upstream if this is important. - -* Tue Jun 08 2010 Dave Jones -- Remove crufty Xen remnants from specfile. - -* Tue Jun 08 2010 Dave Jones -- Remove mkinitrd ifdefs. Dracut or GTFO. - -* Thu Jun 03 2010 Kyle McMartin -- Build kernel headers on s390. - -* Wed Jun 02 2010 Kyle McMartin 2.6.34-20 -- Disable doc_build_fail because xmlto et al. are crud. - -* Wed Jun 02 2010 Kyle McMartin 2.6.34-19 -- Enable -debug flavour builds, until we branch for 2.6.35-rcX. - -* Wed Jun 02 2010 Kyle McMartin -- revert writeback fixes for now, there appear to be dragons - lurking there still. - -* Tue Jun 01 2010 Kyle McMartin 2.6.34-18 -- fix mismerge in i915_gem.c, drm_gem_object_alloc is now - i915_gem_alloc_object. -- add a hunk to rcu_read{,un}lock in sched_fair too. - -* Tue Jun 01 2010 Kyle McMartin 2.6.34-17 -- backport writeback fixes from Jens until stable@ picks them up. - -* Tue Jun 01 2010 Kyle McMartin 2.6.34-16 -- quiet-prove_RCU-in-cgroups.patch: shut RCU lockdep up - as in 8b08ca52f5942c21564bbb90ccfb61053f2c26a1. - -* Tue Jun 01 2010 Kyle McMartin -- disable radeon_pm for now. - -* Mon May 31 2010 Kyle McMartin 2.6.34-14 -- re-add drm-next.patch, should be in sync with 2.6.35 and what - was backported to Fedora 13. -- drop patches merged in drm-next to 2.6.35 -- rebase relevant iwl fixes on top of 2.6.34 from the ones committed - to F-13 by linville. - -* Wed May 26 2010 Adam Jackson -- config-generic: Stop building i830.ko - -* Wed May 26 2010 Kyle McMartin -- iwlwifi-recover_from_tx_stall.patch: copy from F-13. - -* Fri May 21 2010 Roland McGrath 2.6.34-11 -- utrace update - -* Fri May 21 2010 Dave Jones -- Update the SELinux mprotect patch with a newer version from Stephen - -* Fri May 21 2010 Roland McGrath -- perf requires libdw now, not libdwarf - -* Fri May 21 2010 Kyle McMartin 2.6.34-6 -- Fixups for virt_console from Amit Shah, thanks! - -* Thu May 20 2010 Kyle McMartin 2.6.34-5 -- disable intel sdvo fixes until dependent code is backported. - -* Thu May 20 2010 Kyle McMartin 2.6.34-4 -- resync a lot of stuff with F-13... -- linux-2.6-acpi-video-export-edid.patch: rebase & copy from F-13 -- acpi-ec-add-delay-before-write.patch: copy from F-13 -- ... and a whole lot more that I can't be bothered typing. - -* Mon May 17 2010 Matthew Garrett -- thinkpad-acpi-fix-backlight.patch: Fix backlight support on some recent - Thinkpads - -* Sun May 16 2010 Kyle McMartin 2.6.34-2 -- Disable strict copy_from_user checking until lirc is fixed. - -* Sun May 16 2010 Kyle McMartin 2.6.34-1 -- Linux 2.6.34 - -* Sun May 16 2010 Kyle McMartin -- Trimmed changelog, see CVS. - ### # The following Emacs magic makes C-c C-e use UTC dates. # Local Variables: From cdf695a9193895c022eaa070953c22ef212badb9 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 20 May 2011 22:13:22 -0400 Subject: [PATCH 58/99] Linux 2.6.38.7-rc1 Fix up context in utrace-ptrace.patch Revert radeon patches already in our radeon update: drm-radeon-kms-fix-gart-setup-on-fusion-parts-v2-backport.patch Drop merged patches: iwlwifi-add-_ack_plpc_check-module-parameters.patch --- ...dd-_ack_plpc_check-module-parameters.patch | 96 ----------------- kernel.spec | 20 ++-- linux-2.6-upstream-reverts.patch | 100 +++++++++++++++++- linux-2.6-utrace-ptrace.patch | 7 +- ...-caching-printk-from-error-to-notice.patch | 17 +-- sources | 1 + 6 files changed, 125 insertions(+), 116 deletions(-) delete mode 100644 iwlwifi-add-_ack_plpc_check-module-parameters.patch diff --git a/iwlwifi-add-_ack_plpc_check-module-parameters.patch b/iwlwifi-add-_ack_plpc_check-module-parameters.patch deleted file mode 100644 index a6211b51e..000000000 --- a/iwlwifi-add-_ack_plpc_check-module-parameters.patch +++ /dev/null @@ -1,96 +0,0 @@ -From sgruszka@redhat.com Mon May 9 15:27:33 2011 -From: Stanislaw Gruszka -To: kernel@lists.fedoraproject.org, stable@kernel.org -Cc: Kyle McMartin , - Stanislaw Gruszka -Subject: [PATCH 2.6.38] iwlwifi: add {ack,plpc}_check module parameters -Date: Mon, 9 May 2011 21:27:30 +0200 -Message-Id: <1304969250-27725-1-git-send-email-sgruszka@redhat.com> - -commit b7977ffaab5187ad75edaf04ac854615cea93828 upstream. - -Add module ack_check, and plcp_check parameters. Ack_check is disabled -by default since is proved that check ack health can cause troubles. -Plcp_check is enabled by default. - -This prevent connection hangs with "low ack count detected" messages. - -Resolves: -https://bugzilla.redhat.com/show_bug.cgi?id=666646 - -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 + - drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ - drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ - drivers/net/wireless/iwlwifi/iwl-rx.c | 8 ++++++-- - 4 files changed, 15 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c -index 3dee87e..d9c87b3 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c -@@ -604,6 +604,7 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, - struct iwl_mod_params iwlagn_mod_params = { - .amsdu_size_8K = 1, - .restart_fw = 1, -+ .plcp_check = true, - /* the rest are 0 by default */ - }; - -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c -index 35239f0..be07643 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -4586,3 +4586,9 @@ MODULE_PARM_DESC(antenna_coupling, - module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO); - MODULE_PARM_DESC(bt_ch_inhibition, - "Disable BT channel inhibition (default: enable)"); -+ -+module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO); -+MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])"); -+ -+module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO); -+MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); -diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h -index a347437..5c0d5f7 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-core.h -+++ b/drivers/net/wireless/iwlwifi/iwl-core.h -@@ -263,6 +263,8 @@ struct iwl_mod_params { - int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ - int antenna; /* def: 0 = both antennas (use diversity) */ - int restart_fw; /* def: 1 = restart firmware */ -+ bool plcp_check; /* def: true = enable plcp health check */ -+ bool ack_check; /* def: false = disable ack health check */ - }; - - /* -diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c -index 87a6fd8..b707617 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-rx.c -+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c -@@ -234,10 +234,13 @@ EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); - void iwl_recover_from_statistics(struct iwl_priv *priv, - struct iwl_rx_packet *pkt) - { -+ const struct iwl_mod_params *mod_params = priv->cfg->mod_params; -+ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - if (iwl_is_any_associated(priv)) { -- if (priv->cfg->ops->lib->check_ack_health) { -+ if (mod_params->ack_check && -+ priv->cfg->ops->lib->check_ack_health) { - if (!priv->cfg->ops->lib->check_ack_health( - priv, pkt)) { - /* -@@ -250,7 +253,8 @@ void iwl_recover_from_statistics(struct iwl_priv *priv, - return; - } - } -- if (priv->cfg->ops->lib->check_plcp_health) { -+ if (mod_params->plcp_check && -+ priv->cfg->ops->lib->check_plcp_health) { - if (!priv->cfg->ops->lib->check_plcp_health( - priv, pkt)) { - /* diff --git a/kernel.spec b/kernel.spec index 4b6af4d27..ab0180635 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 27 +%global baserelease 28 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,9 +63,9 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 6 +%define stable_update 7 # Is it a -stable RC? -%define stable_rc 0 +%define stable_rc 1 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -741,9 +741,6 @@ Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-availabl # Fix breakage of PCI network adapter names on older Dell systems Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch -# iwlwifi: add {ack,plpc}_check module parameters (#666646) -Patch12405: iwlwifi-add-_ack_plpc_check-module-parameters.patch - # intel_ips driver bug (#703511) causes cooling fan to run Patch12406: ips-use-interruptible-waits-in-ips-monitor.patch @@ -1383,9 +1380,6 @@ ApplyPatch linux-2.6-netconsole-deadlock.patch # CVE-2011-1581 ApplyPatch bonding-incorrect-tx-queue-offset.patch -# iwlwifi: add {ack,plpc}_check module parameters (#666646) queued for stable -ApplyPatch iwlwifi-add-_ack_plpc_check-module-parameters.patch - # intel_ips driver bug (#703511) causes cooling fan to run ApplyPatch ips-use-interruptible-waits-in-ips-monitor.patch @@ -1999,6 +1993,14 @@ fi # and build. %changelog +* Fri May 20 2011 Chuck Ebbert +- Linux 2.6.38.7-rc1 +- Fix up context in utrace-ptrace.patch +- Revert radeon patches already in our radeon update: + drm-radeon-kms-fix-gart-setup-on-fusion-parts-v2-backport.patch +- Drop merged patches: + iwlwifi-add-_ack_plpc_check-module-parameters.patch + * Fri May 13 2011 Kyle McMartin 2.6.38.6-28 - [fabbione@] Fix a deadlock when using hp_sw with an HP san. (7a1e9d82 upstream) diff --git a/linux-2.6-upstream-reverts.patch b/linux-2.6-upstream-reverts.patch index 607602cfc..a8ec0e390 100644 --- a/linux-2.6-upstream-reverts.patch +++ b/linux-2.6-upstream-reverts.patch @@ -1 +1,99 @@ -nil +From alexdeucher@gmail.com Mon May 9 16:35:34 2011 +From: Alex Deucher +Date: Fri, 6 May 2011 14:29:55 -0400 +Subject: [stable] [PATCH] drm/radeon/kms: fix gart setup on fusion parts (v2) backport +To: stable@kernel.org +Cc: Alex Deucher , airlied@redhat.com, gregkh@suse.de +Message-ID: <1304706595-9781-1-git-send-email-alexdeucher@gmail.com> + +From: Alex Deucher + +Backport of 8aeb96f80232e9a701b5c4715504f4c9173978bd +(drm/radeon/kms: fix gart setup on fusion parts (v2)) +to the stable tree. + +Out of the entire GART/VM subsystem, the hw designers changed +the location of 3 regs. + +v2: airlied: add parameter for userspace to work from. + +Signed-off-by: Alex Deucher +Signed-off-by: Jerome Glisse +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/radeon/evergreen.c | 17 +++++++++-------- + drivers/gpu/drm/radeon/evergreend.h | 5 +++++ + drivers/gpu/drm/radeon/radeon_kms.c | 3 +++ + include/drm/radeon_drm.h | 1 + + 4 files changed, 18 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -869,9 +869,15 @@ int evergreen_pcie_gart_enable(struct ra + SYSTEM_ACCESS_MODE_NOT_IN_SYS | + SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | + EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); +- WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); +- WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); +- WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); ++ if (rdev->flags & RADEON_IS_IGP) { ++ WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp); ++ WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp); ++ WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp); ++ } else { ++ WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); ++ WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); ++ WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); ++ } + WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); + WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); +@@ -2930,11 +2936,6 @@ static int evergreen_startup(struct rade + rdev->asic->copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } +- /* XXX: ontario has problems blitting to gart at the moment */ +- if (rdev->family == CHIP_PALM) { +- rdev->asic->copy = NULL; +- radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); +- } + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -221,6 +221,11 @@ + #define MC_VM_MD_L1_TLB0_CNTL 0x2654 + #define MC_VM_MD_L1_TLB1_CNTL 0x2658 + #define MC_VM_MD_L1_TLB2_CNTL 0x265C ++ ++#define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C ++#define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 ++#define FUS_MC_VM_MD_L1_TLB2_CNTL 0x2664 ++ + #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C + #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 + #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 +--- a/drivers/gpu/drm/radeon/radeon_kms.c ++++ b/drivers/gpu/drm/radeon/radeon_kms.c +@@ -205,6 +205,9 @@ int radeon_info_ioctl(struct drm_device + /* return clock value in KHz */ + value = rdev->clock.spll.reference_freq * 10; + break; ++ case RADEON_INFO_FUSION_GART_WORKING: ++ value = 1; ++ break; + default: + DRM_DEBUG_KMS("Invalid request %d\n", info->request); + return -EINVAL; +--- a/include/drm/radeon_drm.h ++++ b/include/drm/radeon_drm.h +@@ -908,6 +908,7 @@ struct drm_radeon_cs { + #define RADEON_INFO_WANT_HYPERZ 0x07 + #define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ + #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ ++#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ + + struct drm_radeon_info { + uint32_t request; diff --git a/linux-2.6-utrace-ptrace.patch b/linux-2.6-utrace-ptrace.patch index bc5681d95..367deb966 100644 --- a/linux-2.6-utrace-ptrace.patch +++ b/linux-2.6-utrace-ptrace.patch @@ -1249,8 +1249,8 @@ index e275608..72ea65c 100644 #include #include @@ -24,7 +23,320 @@ - #include #include + #include +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ @@ -1955,7 +1955,7 @@ index e275608..72ea65c 100644 int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { -@@ -851,42 +876,5 @@ int compat_ptrace_request(struct task_st +@@ -851,45 +876,8 @@ int compat_ptrace_request(struct task_st return ret; } @@ -1999,6 +1999,9 @@ index e275608..72ea65c 100644 -} #endif /* CONFIG_COMPAT */ +#endif /* CONFIG_UTRACE */ + + #ifdef CONFIG_HAVE_HW_BREAKPOINT + int ptrace_get_breakpoints(struct task_struct *tsk) diff --git a/kernel/utrace.c b/kernel/utrace.c index 26d6faf..37dce16 100644 --- a/kernel/utrace.c diff --git a/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch b/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch index 47ebbaddb..c082fe05f 100644 --- a/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch +++ b/scsi-sd-downgrade-caching-printk-from-error-to-notice.patch @@ -2,20 +2,21 @@ diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e567302..261638a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c -@@ -1988,11 +1988,11 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) +@@ -1956,12 +1956,12 @@ sd_read_cache_type(struct scsi_disk *sdk + int offset = data.header_length + data.block_descriptor_length; + + if (offset >= SD_BUF_SIZE - 2) { +- sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); ++ sd_printk(KERN_NOTICE, sdkp, "Malformed MODE SENSE response\n"); + goto defaults; } - if (modepage == 0x3F) { -- sd_printk(KERN_ERR, sdkp, "No Caching mode page " -+ sd_printk(KERN_NOTICE, sdkp, "No Caching mode page " - "present\n"); - goto defaults; - } else if ((buffer[offset] & 0x3f) != modepage) { + if ((buffer[offset] & 0x3f) != modepage) { - sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); + sd_printk(KERN_NOTICE, sdkp, "Got wrong page\n"); goto defaults; } - Page_found: + @@ -2033,7 +2033,7 @@ bad_sense: sd_printk(KERN_ERR, sdkp, "Asking for cache data failed\n"); diff --git a/sources b/sources index cd4a5e33c..b3f1d0ee0 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 527fab8162c682ad849eb21fc30d28ef patch-2.6.38.6.bz2 +10c4659d759236f1e71fe2431adcc957 patch-2.6.38.7-rc1.bz2 From 7a131a574fe53376258c68641e223496f705b6d1 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 20 May 2011 22:35:34 -0400 Subject: [PATCH 59/99] Fix stalls on AMD Sempron notebooks (#704059) --- kernel.spec | 11 +++++++++-- x86-amd-arat-bug-on-sempron-workaround.patch | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 x86-amd-arat-bug-on-sempron-workaround.patch diff --git a/kernel.spec b/kernel.spec index ab0180635..42e7503ba 100644 --- a/kernel.spec +++ b/kernel.spec @@ -746,6 +746,9 @@ Patch12406: ips-use-interruptible-waits-in-ips-monitor.patch Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch +# temporary fix for Sempron machines stalling (#704059) +Patch12408: x86-amd-arat-bug-on-sempron-workaround.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1385,6 +1388,9 @@ ApplyPatch ips-use-interruptible-waits-in-ips-monitor.patch ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch +# temporary fix for Sempron machines stalling (#704059) +ApplyPatch x86-amd-arat-bug-on-sempron-workaround.patch + # END OF PATCH APPLICATIONS %endif @@ -1993,15 +1999,16 @@ fi # and build. %changelog -* Fri May 20 2011 Chuck Ebbert +* Fri May 20 2011 Chuck Ebbert 2.6.38.7-28.rc1 - Linux 2.6.38.7-rc1 - Fix up context in utrace-ptrace.patch - Revert radeon patches already in our radeon update: drm-radeon-kms-fix-gart-setup-on-fusion-parts-v2-backport.patch - Drop merged patches: iwlwifi-add-_ack_plpc_check-module-parameters.patch +- Fix stalls on AMD Sempron notebooks (#704059) -* Fri May 13 2011 Kyle McMartin 2.6.38.6-28 +* Fri May 13 2011 Kyle McMartin 2.6.38.6-27 - [fabbione@] Fix a deadlock when using hp_sw with an HP san. (7a1e9d82 upstream) diff --git a/x86-amd-arat-bug-on-sempron-workaround.patch b/x86-amd-arat-bug-on-sempron-workaround.patch new file mode 100644 index 000000000..262293b00 --- /dev/null +++ b/x86-amd-arat-bug-on-sempron-workaround.patch @@ -0,0 +1,18 @@ +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -724,6 +724,15 @@ bool cpu_has_amd_erratum(const int *erra + if (cpu->x86_vendor != X86_VENDOR_AMD) + return false; + ++ /* ++ * Temporary workaround for ARAT bug on Sempron. ++ * The BIOS clears the bit in OSVW, so the check ++ * fails, then ARAT gets set and when the processor ++ * uses C3 it hangs. Always return true for that CPU. ++ */ ++ if (cpu->x86 == 0x10 && cpu->x86_model == 6 && cpu->x86_mask == 2) ++ return true; ++ + if (osvw_id >= 0 && osvw_id < 65536 && + cpu_has(cpu, X86_FEATURE_OSVW)) { + u64 osvw_len; From 3cc5871fa60230780816b5abde3b96364786b788 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 23 May 2011 10:06:38 -0400 Subject: [PATCH 60/99] Linux 2.6.38.7 --- kernel.spec | 7 +++++-- sources | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel.spec b/kernel.spec index 42e7503ba..ea87af2bd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 28 +%global baserelease 29 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -65,7 +65,7 @@ Summary: The Linux kernel # Do we have a -stable update to apply? %define stable_update 7 # Is it a -stable RC? -%define stable_rc 1 +%define stable_rc 0 # Set rpm version accordingly %if 0%{?stable_update} %define stablerev .%{stable_update} @@ -1999,6 +1999,9 @@ fi # and build. %changelog +* Mon May 23 2011 Chuck Ebbert 2.6.38.7-29 +- Linux 2.6.38.7 + * Fri May 20 2011 Chuck Ebbert 2.6.38.7-28.rc1 - Linux 2.6.38.7-rc1 - Fix up context in utrace-ptrace.patch diff --git a/sources b/sources index b3f1d0ee0..b582c97ed 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -527fab8162c682ad849eb21fc30d28ef patch-2.6.38.6.bz2 -10c4659d759236f1e71fe2431adcc957 patch-2.6.38.7-rc1.bz2 +2639b4b98a2dcfc8b7f091543f289205 patch-2.6.38.7.bz2 From fcfc30ed64d8ea48d8f101829893105c66604627 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Mon, 23 May 2011 10:27:34 -0400 Subject: [PATCH 61/99] Eliminate hangs when using frequent high-order allocations --- kernel.spec | 11 ++ ...dat_balanced-in-sleeping_prematurely.patch | 114 +++++++++++++ ...r-should-schedule-during-shrink_slab.patch | 153 ++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch create mode 100644 mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch diff --git a/kernel.spec b/kernel.spec index ea87af2bd..0b26eb252 100644 --- a/kernel.spec +++ b/kernel.spec @@ -749,6 +749,11 @@ Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch # temporary fix for Sempron machines stalling (#704059) Patch12408: x86-amd-arat-bug-on-sempron-workaround.patch +# Eliminate hangs when using frequent high-order allocations V4 +# (will be in 2.6.38.8) +Patch12410: mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch +Patch12411: mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1391,6 +1396,11 @@ ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch # temporary fix for Sempron machines stalling (#704059) ApplyPatch x86-amd-arat-bug-on-sempron-workaround.patch +# Eliminate hangs when using frequent high-order allocations V4 +# (will be in 2.6.38.8) +ApplyPatch mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch +ApplyPatch mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch + # END OF PATCH APPLICATIONS %endif @@ -2001,6 +2011,7 @@ fi %changelog * Mon May 23 2011 Chuck Ebbert 2.6.38.7-29 - Linux 2.6.38.7 +- Eliminate hangs when using frequent high-order allocations * Fri May 20 2011 Chuck Ebbert 2.6.38.7-28.rc1 - Linux 2.6.38.7-rc1 diff --git a/mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch b/mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch new file mode 100644 index 000000000..a619a59ad --- /dev/null +++ b/mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch @@ -0,0 +1,114 @@ +Return-Path: stable-bounces@linux.kernel.org +Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO + zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by + mail02.corp.redhat.com with LMTP; Mon, 23 May 2011 05:54:46 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3139D4E5E6 + for ; Mon, 23 May 2011 05:54:46 -0400 (EDT) +Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id Xko2+8bJJ7po for ; + Mon, 23 May 2011 05:54:46 -0400 (EDT) +Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) + by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A5854D284 + for ; Mon, 23 May 2011 05:54:46 -0400 (EDT) +Received: from mx1.redhat.com (ext-mx13.extmail.prod.ext.phx2.redhat.com [10.5.110.18]) + by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p4N9sjdi005829 + for ; Mon, 23 May 2011 05:54:45 -0400 +Received: from hera.kernel.org (hera.kernel.org [140.211.167.34]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4N9siLf018408 + for ; Mon, 23 May 2011 05:54:45 -0400 +Received: from hera.kernel.org (localhost [127.0.0.1]) + by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9s7Yv010104; + Mon, 23 May 2011 09:54:09 GMT +X-Virus-Status: Clean +X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org +Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) + by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9s1LC009736; + Mon, 23 May 2011 09:54:02 GMT +X-Virus-Status: Clean +X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org +Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) + by mx2.suse.de (Postfix) with ESMTP id 98E7590072; + Mon, 23 May 2011 11:53:59 +0200 (CEST) +From: Mel Gorman +To: Andrew Morton +Date: Mon, 23 May 2011 10:53:54 +0100 +Message-Id: <1306144435-2516-2-git-send-email-mgorman@suse.de> +In-Reply-To: <1306144435-2516-1-git-send-email-mgorman@suse.de> +References: <1306144435-2516-1-git-send-email-mgorman@suse.de> +X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED + autolearn=unavailable version=3.3.2-r929478 +X-Spam-Checker-Version: SpamAssassin 3.3.2-r929478 (2010-03-31) on + hera.kernel.org +X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.2.3 (hera.kernel.org [127.0.0.1]); Mon, 23 May 2011 09:54:12 +0000 (UTC) +X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by + milter-greylist-4.2.3 (hera.kernel.org [140.211.167.34]); + Mon, 23 May 2011 09:54:04 +0000 (UTC) +Cc: Pekka Enberg , Rik van Riel , + Jan Kara , linux-kernel , + James Bottomley , + linux-mm , Minchan Kim , + Raghavendra D Prabhu , + Johannes Weiner , + linux-fsdevel , + Colin King , + Christoph Lameter , + linux-ext4 , stable , + Chris Mason , Mel Gorman +Subject: [stable] [PATCH 1/2] mm: vmscan: Correct use of pgdat_balanced in + sleeping_prematurely +X-BeenThere: stable@linux.kernel.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: For maintainers of the stable Linux series +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +Sender: stable-bounces@linux.kernel.org +Errors-To: stable-bounces@linux.kernel.org +X-RedHat-Spam-Score: -2.31 (RCVD_IN_DNSWL_MED,T_RP_MATCHES_RCVD) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 +X-Scanned-By: MIMEDefang 2.68 on 10.5.110.18 + +From: Johannes Weiner + +Johannes Weiner poined out that the logic in commit [1741c877: mm: +kswapd: keep kswapd awake for high-order allocations until a percentage +of the node is balanced] is backwards. Instead of allowing kswapd to go +to sleep when balancing for high order allocations, it keeps it kswapd +running uselessly. + +Signed-off-by: Mel Gorman +Reviewed-by: Rik van Riel +--- + mm/vmscan.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 8bfd450..1aa262b 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2286,7 +2286,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining, + * must be balanced + */ + if (order) +- return pgdat_balanced(pgdat, balanced, classzone_idx); ++ return !pgdat_balanced(pgdat, balanced, classzone_idx); + else + return !all_zones_ok; + } +-- +1.7.3.4 + +_______________________________________________ +stable mailing list +stable@linux.kernel.org +http://linux.kernel.org/mailman/listinfo/stable diff --git a/mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch b/mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch new file mode 100644 index 000000000..b5b053eac --- /dev/null +++ b/mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch @@ -0,0 +1,153 @@ +Return-Path: stable-bounces@linux.kernel.org +Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO + zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by + mail02.corp.redhat.com with LMTP; Mon, 23 May 2011 05:54:49 -0400 (EDT) +Received: from localhost (localhost.localdomain [127.0.0.1]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 443AC9289D + for ; Mon, 23 May 2011 05:54:49 -0400 (EDT) +Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) + by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id WTG56s2uAm8Z for ; + Mon, 23 May 2011 05:54:49 -0400 (EDT) +Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) + by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D1D2906E4 + for ; Mon, 23 May 2011 05:54:49 -0400 (EDT) +Received: from mx1.redhat.com (ext-mx11.extmail.prod.ext.phx2.redhat.com [10.5.110.16]) + by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p4N9snmk002150 + for ; Mon, 23 May 2011 05:54:49 -0400 +Received: from hera.kernel.org (hera.kernel.org [140.211.167.34]) + by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4N9smZs008302 + for ; Mon, 23 May 2011 05:54:48 -0400 +Received: from hera.kernel.org (localhost [127.0.0.1]) + by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9sGZo010150; + Mon, 23 May 2011 09:54:16 GMT +X-Virus-Status: Clean +X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org +Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) + by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9s1xm009737; + Mon, 23 May 2011 09:54:02 GMT +X-Virus-Status: Clean +X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org +Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) + by mx2.suse.de (Postfix) with ESMTP id 2B4998FFEB; + Mon, 23 May 2011 11:54:01 +0200 (CEST) +From: Mel Gorman +To: Andrew Morton +Date: Mon, 23 May 2011 10:53:55 +0100 +Message-Id: <1306144435-2516-3-git-send-email-mgorman@suse.de> +In-Reply-To: <1306144435-2516-1-git-send-email-mgorman@suse.de> +References: <1306144435-2516-1-git-send-email-mgorman@suse.de> +X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED + autolearn=unavailable version=3.3.2-r929478 +X-Spam-Checker-Version: SpamAssassin 3.3.2-r929478 (2010-03-31) on + hera.kernel.org +X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.2.3 (hera.kernel.org [127.0.0.1]); Mon, 23 May 2011 09:54:16 +0000 (UTC) +X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by + milter-greylist-4.2.3 (hera.kernel.org [140.211.167.34]); + Mon, 23 May 2011 09:54:03 +0000 (UTC) +Cc: Pekka Enberg , Rik van Riel , + Jan Kara , linux-kernel , + James Bottomley , + linux-mm , Minchan Kim , + Raghavendra D Prabhu , + Johannes Weiner , + linux-fsdevel , + Colin King , + Christoph Lameter , + linux-ext4 , stable , + Chris Mason , Mel Gorman +Subject: [stable] [PATCH 2/2] mm: vmscan: Correctly check if reclaimer + should schedule during shrink_slab +X-BeenThere: stable@linux.kernel.org +X-Mailman-Version: 2.1.12 +Precedence: list +List-Id: For maintainers of the stable Linux series +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +Sender: stable-bounces@linux.kernel.org +Errors-To: stable-bounces@linux.kernel.org +X-RedHat-Spam-Score: -2.31 (RCVD_IN_DNSWL_MED,T_RP_MATCHES_RCVD) +X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 +X-Scanned-By: MIMEDefang 2.68 on 10.5.110.16 + +It has been reported on some laptops that kswapd is consuming large +amounts of CPU and not being scheduled when SLUB is enabled during +large amounts of file copying. It is expected that this is due to +kswapd missing every cond_resched() point because; + +shrink_page_list() calls cond_resched() if inactive pages were isolated + which in turn may not happen if all_unreclaimable is set in + shrink_zones(). If for whatver reason, all_unreclaimable is + set on all zones, we can miss calling cond_resched(). + +balance_pgdat() only calls cond_resched if the zones are not + balanced. For a high-order allocation that is balanced, it + checks order-0 again. During that window, order-0 might have + become unbalanced so it loops again for order-0 and returns + that it was reclaiming for order-0 to kswapd(). It can then + find that a caller has rewoken kswapd for a high-order and + re-enters balance_pgdat() without ever calling cond_resched(). + +shrink_slab only calls cond_resched() if we are reclaiming slab + pages. If there are a large number of direct reclaimers, the + shrinker_rwsem can be contended and prevent kswapd calling + cond_resched(). + +This patch modifies the shrink_slab() case. If the semaphore is +contended, the caller will still check cond_resched(). After each +successful call into a shrinker, the check for cond_resched() remains +in case one shrinker is particularly slow. + +This patch replaces +mm-vmscan-if-kswapd-has-been-running-too-long-allow-it-to-sleep.patch +in -mm. + +[mgorman@suse.de: Preserve call to cond_resched after each call into shrinker] +From: Minchan Kim +Signed-off-by: Mel Gorman +--- + mm/vmscan.c | 9 +++++++-- + 1 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 1aa262b..cc1470b 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -230,8 +230,11 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, + if (scanned == 0) + scanned = SWAP_CLUSTER_MAX; + +- if (!down_read_trylock(&shrinker_rwsem)) +- return 1; /* Assume we'll be able to shrink next time */ ++ if (!down_read_trylock(&shrinker_rwsem)) { ++ /* Assume we'll be able to shrink next time */ ++ ret = 1; ++ goto out; ++ } + + list_for_each_entry(shrinker, &shrinker_list, list) { + unsigned long long delta; +@@ -282,6 +285,8 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, + shrinker->nr += total_scan; + } + up_read(&shrinker_rwsem); ++out: ++ cond_resched(); + return ret; + } + +-- +1.7.3.4 + +_______________________________________________ +stable mailing list +stable@linux.kernel.org +http://linux.kernel.org/mailman/listinfo/stable From e56d28112674d1b36a4c40dbabd434aab2fad0f3 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 24 May 2011 11:03:28 -0400 Subject: [PATCH 62/99] backport some low impact enablement for the pegatron tables --- ...-for-ath3k-on-pegatron-lucid-tablets.patch | 37 +++++++++ ...uch-add-support-for-elo-touchsystems.patch | 78 +++++++++++++++++++ kernel.spec | 11 +++ 3 files changed, 126 insertions(+) create mode 100644 bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch create mode 100644 hid-multitouch-add-support-for-elo-touchsystems.patch diff --git a/bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch b/bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch new file mode 100644 index 000000000..767105587 --- /dev/null +++ b/bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch @@ -0,0 +1,37 @@ +From: Andy Ross +Date: Mon, 9 May 2011 23:11:16 +0000 (-0700) +Subject: Bluetooth: Device ids for ath3k on Pegatron Lucid tablets +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fpadovan%2Fbluetooth-next-2.6.git;a=commitdiff_plain;h=2a7bccccdb9604a717c2128a931f022267d35629 + +Bluetooth: Device ids for ath3k on Pegatron Lucid tablets + +New ath3k device IDs used on the Pegatron Lucid (ExoPC and WeTab) units. + +Signed-off-by: Andy Ross +Signed-off-by: Gustavo F. Padovan +--- + +diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c +index 695d441..6bacef3 100644 +--- a/drivers/bluetooth/ath3k.c ++++ b/drivers/bluetooth/ath3k.c +@@ -62,6 +62,7 @@ static struct usb_device_id ath3k_table[] = { + + /* Atheros AR3011 with sflash firmware*/ + { USB_DEVICE(0x0CF3, 0x3002) }, ++ { USB_DEVICE(0x13d3, 0x3304) }, + + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03F0, 0x311D) }, +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 762a510..c2de895 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -104,6 +104,7 @@ static struct usb_device_id blacklist_table[] = { + + /* Atheros 3011 with sflash firmware */ + { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, ++ { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, + + /* Atheros AR9285 Malbec with sflash firmware */ + { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, diff --git a/hid-multitouch-add-support-for-elo-touchsystems.patch b/hid-multitouch-add-support-for-elo-touchsystems.patch new file mode 100644 index 000000000..1294f4630 --- /dev/null +++ b/hid-multitouch-add-support-for-elo-touchsystems.patch @@ -0,0 +1,78 @@ +From: Benjamin Tissoires +Date: Thu, 19 May 2011 09:37:29 +0000 (+0200) +Subject: HID: hid-multitouch: add support for Elo TouchSystems 2515 IntelliTouch Plus +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjikos%2Fhid.git;a=commitdiff_plain;h=c04abeeff9d76a703cac1e6d312853b0fc8136f5 + +HID: hid-multitouch: add support for Elo TouchSystems 2515 IntelliTouch Plus + +This patch adds support for Elo TouchSystems 2515 IntelliTouch Plus +that can be found in Lenovo A700 all-in-one. + +Signed-off-by: Benjamin Tissoires +Tested-by: Bastien Nocera +Signed-off-by: Jiri Kosina + +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -309,6 +309,7 @@ config HID_MULTITOUCH + + Say Y here if you have one of the following devices: + - Cypress TrueTouch panels ++ - Elo TouchSystems IntelliTouch Plus panels + - Hanvon dual touch panels + - Pixcir dual touch panels + - 'Sensing Win7-TwoFinger' panel by GeneralTouch +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1335,6 +1335,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, + { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, + { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -219,6 +219,7 @@ + #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 + + #define USB_VENDOR_ID_ELO 0x04E7 ++#define USB_DEVICE_ID_ELO_TS2515 0x0022 + #define USB_DEVICE_ID_ELO_TS2700 0x0020 + + #define USB_VENDOR_ID_EMS 0x2006 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -69,6 +69,7 @@ struct mt_class { + #define MT_CLS_DUAL1 2 + #define MT_CLS_DUAL2 3 + #define MT_CLS_CYPRESS 4 ++#define MT_CLS_DUAL_NSMU_CONTACTID 5 + + /* + * these device-dependent functions determine what slot corresponds +@@ -119,6 +120,11 @@ struct mt_class mt_classes[] = { + MT_QUIRK_CYPRESS, + .maxcontacts = 10 }, + ++ { .name = MT_CLS_DUAL_NSMU_CONTACTID, ++ .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | ++ MT_QUIRK_SLOT_IS_CONTACTID, ++ .maxcontacts = 2 }, ++ + { } + }; + +@@ -465,6 +471,11 @@ static const struct hid_device_id mt_devices[] = { + HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, + USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, + ++ /* Elo TouchSystems IntelliTouch Plus panel */ ++ { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, ++ HID_USB_DEVICE(USB_VENDOR_ID_ELO, ++ USB_DEVICE_ID_ELO_TS2515) }, ++ + /* GeneralTouch panel */ + { .driver_data = MT_CLS_DUAL2, + HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, diff --git a/kernel.spec b/kernel.spec index 0b26eb252..15b2bc1c0 100644 --- a/kernel.spec +++ b/kernel.spec @@ -754,6 +754,9 @@ Patch12408: x86-amd-arat-bug-on-sempron-workaround.patch Patch12410: mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch Patch12411: mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch +Patch12415: hid-multitouch-add-support-for-elo-touchsystems.patch +Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1401,6 +1404,9 @@ ApplyPatch x86-amd-arat-bug-on-sempron-workaround.patch ApplyPatch mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch ApplyPatch mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch +ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch +ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch + # END OF PATCH APPLICATIONS %endif @@ -2009,6 +2015,11 @@ fi # and build. %changelog +* Tue May 24 2011 Kyle McMartin +- hid-multitouch: add support for elo touchsystems panels (requested + by hadess, backported from hid-next) +- bluetooth: add support for more ath3k devices (Ditto.) + * Mon May 23 2011 Chuck Ebbert 2.6.38.7-29 - Linux 2.6.38.7 - Eliminate hangs when using frequent high-order allocations From b1f66838e692b67bcbb4ec24d6bd9efe0f97bb5c Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 25 May 2011 12:13:49 -0400 Subject: [PATCH 63/99] acpi_reboot.patch is upstream now --- acpi_reboot.patch | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/acpi_reboot.patch b/acpi_reboot.patch index a980b31f7..82bffaa64 100644 --- a/acpi_reboot.patch +++ b/acpi_reboot.patch @@ -1,4 +1,8 @@ -Improve our reboot handling for compatibility with Windows. Upstream in .38? +Improve our reboot handling for compatibility with Windows. + +Upstream commits: +660e34cebf0a11d54f2d5dd8838607452355f321 +f17d9cbf20c4734c4199caa6dee87047f2f8278f diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index c495aa8..c770e66 100644 From f6fc553f93ef953a159f59e9e0c176b8ecbd4860 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 25 May 2011 22:48:20 -0400 Subject: [PATCH 64/99] drm-radeon-update2.patch: more radeon updates + cayman accel support --- drm-radeon-update2.patch | 1708 ++++++++++++++++++++++++++++++++++++++ kernel.spec | 5 + 2 files changed, 1713 insertions(+) create mode 100644 drm-radeon-update2.patch diff --git a/drm-radeon-update2.patch b/drm-radeon-update2.patch new file mode 100644 index 000000000..1224c0fba --- /dev/null +++ b/drm-radeon-update2.patch @@ -0,0 +1,1708 @@ +commit 05d1ee2878c955f7cf4254ed7f94bd65758f9208 +Author: Alex Deucher +Date: Wed May 25 01:00:45 2011 -0400 + + drm/radeon/kms/blit: workaround some hw issues on evergreen+ + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit e520c516656b3c361ebf8add4e00428b7c37afd6 +Author: Alex Deucher +Date: Wed May 25 16:39:00 2011 -0400 + + drm/radeon/kms: add blit support for cayman (v2) + + Allows us to use the 3D engine for memory management + and allows us to use vram beyond the BAR aperture. + + v2: fix copy paste typo + Reported-by: Nils Wallménius + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit e1b12b63f9df3a5480972c21f504163b36ceaa88 +Author: Alex Deucher +Date: Wed May 25 18:45:37 2011 -0400 + + drm/radeon/kms: fix thermal sensor reading on juniper + + Uses a different method than other evergreen asics. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 46f21922e84d074158781368eee24727a60f9d32 +Author: Alex Deucher +Date: Wed May 25 17:49:54 2011 -0400 + + drm/radeon/kms: add missing case for cayman thermal sensor + + The rest of the code is already in place. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 8cc42a1f51ada532c76009fd8b3261d5e7e8f02b +Author: Alex Deucher +Date: Fri May 20 12:35:23 2011 -0400 + + drm/radeon/kms: bump kms version number + + - proper bank size for fusion for 2D tiling. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit e0014e347d1d15e12c5beffd6af9d22a8d495969 +Author: Alex Deucher +Date: Fri May 20 12:35:22 2011 -0400 + + drm/radeon/kms: properly set num banks for fusion asics + + Needed by userspace for 2D tiled buffer alignment + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 48c7304eb2af97b6e50a93e22b656c9f3ead5f90 +Author: Alex Deucher +Date: Mon May 23 14:22:26 2011 -0400 + + drm/radeon/kms/cayman: fix typo in register mask + + Noticed by Droste on IRC. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 13e5c224cdd62fc3d454f1ef6d8157181ade07d9 +Author: Dave Airlie +Date: Thu May 19 14:14:41 2011 +1000 + + drm/radeon/kms: fix tile_config value reported to userspace on cayman. + + cayman is reporting the wrong tile config value to userspace, this + causes piglit mipmap generation tests to fail. + + Reviewed-by: Alex Deucher + cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit a9b83345a9c37d3bdea30be5a7d0cd34a0f28a68 +Author: Dave Airlie +Date: Thu May 19 14:14:40 2011 +1000 + + drm/radeon/kms: fix incorrect comparison in cayman setup code. + + This was leading to a bogus value being programmed to the backend + routing register. + + Reviewed-by: Alex Deucher + cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 4f71384abcb866214a927510d7e315ad00692faa +Author: Dave Airlie +Date: Thu May 19 14:14:43 2011 +1000 + + drm/radeon/kms: add wait idle ioctl for eg->cayman + + None of the latest GPUs had this hooked up, this is necessary for + correct operation in a lot of cases, however we should test this on a few + GPUs in these families as we've had problems in this area before. + + Reviewed-by: Alex Deucher + cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 0676d9dc1e66566af98e1192a041c9e983a69eaf +Author: Dave Airlie +Date: Thu May 19 14:14:42 2011 +1000 + + drm/radeon/cayman: setup hdp to invalidate and flush when asked + + On cayman we need to set the bit to cause HDP flushes to invalidate the + HDP cache also. + + Reviewed-by: Alex Deucher + cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 5e9df070bdc59db0b8718b8e2e6a387e49acda7c +Author: Alex Deucher +Date: Thu May 19 11:07:57 2011 -0400 + + drm/radeon/evergreen/btc/fusion: setup hdp to invalidate and flush when asked + + This needs to be explicitly set on btc. It's set by default + on evergreen/fusion, so it fine to just unconditionally enable it for + all chips. + + Signed-off-by: Alex Deucher + cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 97bce584876b2293c0ceeeb1abc33ec568d320ea +Author: Alex Deucher +Date: Thu May 12 21:15:15 2011 -0400 + + drm/radeon/kms: add some evergreen/ni safe regs + + need to programmed from the userspace drivers. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit d3be86b8137152ebf1be2ee2ccf90fea7f9a07a9 +Author: Alex Deucher +Date: Wed May 11 03:15:24 2011 -0400 + + drm/radeon/kms: fix tiling reg on fusion + + The location of MC_ARB_RAMCFG changed on fusion. + I've diffed all the other regs in evergreend.h and this + is the only other reg that changed. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 740da77e0792cd804510d018924df8f149f58fe4 +Author: Alex Deucher +Date: Tue May 10 02:14:52 2011 +0000 + + drm/radeon/kms: fix cayman acceleration + + The TCC disable setup was incorrect. This + prevents the GPU from hanging when draw commands + are issued. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 02b1b583d1c9b2559288ea5f46f04b0c8385f1ef +Author: Dave Airlie +Date: Mon May 9 14:54:33 2011 +1000 + + drm/radeon: fix cayman struct accessors. + + We are accessing totally the wrong struct in this case, and putting + uninitialised values into the GPU, which it doesn't like unsurprisingly. + + Signed-off-by: Dave Airlie + +commit 202ea65cf5d6451baf74feb4becdad19ab53eadc +Author: Ilija Hadzic +Date: Wed May 4 20:15:03 2011 -0400 + + drm/radeon: fix order of doing things in radeon_crtc_cursor_set + + if object pin or object lookup in radeon_cursor_set fail, the function + could leave inconsistent mouse width and hight values in radeon_crtc + fixed by moving cursor width and height assignments after all + checks have passed + + Signed-off-by: Ilija Hadzic + Reviewed-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit a796f1fc096d0032972480657d6d9c4fc5836496 +Author: Alex Deucher +Date: Fri May 6 01:42:49 2011 -0400 + + drm/radeon/kms: ATPX switcheroo fixes + + When we switch the display mux, also switch + the i2c mux. Also use the start and finish + methods to let the sbios know that the switch + is happening. + + Should fix: + https://bugs.freedesktop.org/show_bug.cgi?id=35398 + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 134627db513fffd8ecc90b96d477c18ae76d2d61 +Author: Alex Deucher +Date: Tue May 3 12:44:54 2011 -0400 + + drm/radeon/kms: add support for thermal chips on combios asics + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie +diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c +index e148ab0..7b4eeb7 100644 +--- a/drivers/gpu/drm/radeon/cayman_blit_shaders.c ++++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c +@@ -39,17 +39,335 @@ + + const u32 cayman_default_state[] = + { +- /* XXX fill in additional blit state */ ++ 0xc0066900, ++ 0x00000000, ++ 0x00000060, /* DB_RENDER_CONTROL */ ++ 0x00000000, /* DB_COUNT_CONTROL */ ++ 0x00000000, /* DB_DEPTH_VIEW */ ++ 0x0000002a, /* DB_RENDER_OVERRIDE */ ++ 0x00000000, /* DB_RENDER_OVERRIDE2 */ ++ 0x00000000, /* DB_HTILE_DATA_BASE */ + + 0xc0026900, +- 0x00000316, +- 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ +- 0x00000010, /* */ ++ 0x0000000a, ++ 0x00000000, /* DB_STENCIL_CLEAR */ ++ 0x00000000, /* DB_DEPTH_CLEAR */ ++ ++ 0xc0036900, ++ 0x0000000f, ++ 0x00000000, /* DB_DEPTH_INFO */ ++ 0x00000000, /* DB_Z_INFO */ ++ 0x00000000, /* DB_STENCIL_INFO */ ++ ++ 0xc0016900, ++ 0x00000080, ++ 0x00000000, /* PA_SC_WINDOW_OFFSET */ ++ ++ 0xc00d6900, ++ 0x00000083, ++ 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ ++ 0x00000000, /* PA_SC_CLIPRECT_0_TL */ ++ 0x20002000, /* PA_SC_CLIPRECT_0_BR */ ++ 0x00000000, ++ 0x20002000, ++ 0x00000000, ++ 0x20002000, ++ 0x00000000, ++ 0x20002000, ++ 0xaaaaaaaa, /* PA_SC_EDGERULE */ ++ 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ ++ 0x0000000f, /* CB_TARGET_MASK */ ++ 0x0000000f, /* CB_SHADER_MASK */ ++ ++ 0xc0226900, ++ 0x00000094, ++ 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ ++ 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x80000000, ++ 0x20002000, ++ 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ ++ 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ ++ ++ 0xc0016900, ++ 0x000000d4, ++ 0x00000000, /* SX_MISC */ + + 0xc0026900, + 0x000000d9, + 0x00000000, /* CP_RINGID */ + 0x00000000, /* CP_VMID */ ++ ++ 0xc0096900, ++ 0x00000100, ++ 0x00ffffff, /* VGT_MAX_VTX_INDX */ ++ 0x00000000, /* VGT_MIN_VTX_INDX */ ++ 0x00000000, /* VGT_INDX_OFFSET */ ++ 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ ++ 0x00000000, /* SX_ALPHA_TEST_CONTROL */ ++ 0x00000000, /* CB_BLEND_RED */ ++ 0x00000000, /* CB_BLEND_GREEN */ ++ 0x00000000, /* CB_BLEND_BLUE */ ++ 0x00000000, /* CB_BLEND_ALPHA */ ++ ++ 0xc0016900, ++ 0x00000187, ++ 0x00000100, /* SPI_VS_OUT_ID_0 */ ++ ++ 0xc0026900, ++ 0x00000191, ++ 0x00000100, /* SPI_PS_INPUT_CNTL_0 */ ++ 0x00000101, /* SPI_PS_INPUT_CNTL_1 */ ++ ++ 0xc0016900, ++ 0x000001b1, ++ 0x00000000, /* SPI_VS_OUT_CONFIG */ ++ ++ 0xc0106900, ++ 0x000001b3, ++ 0x20000001, /* SPI_PS_IN_CONTROL_0 */ ++ 0x00000000, /* SPI_PS_IN_CONTROL_1 */ ++ 0x00000000, /* SPI_INTERP_CONTROL_0 */ ++ 0x00000000, /* SPI_INPUT_Z */ ++ 0x00000000, /* SPI_FOG_CNTL */ ++ 0x00100000, /* SPI_BARYC_CNTL */ ++ 0x00000000, /* SPI_PS_IN_CONTROL_2 */ ++ 0x00000000, /* SPI_COMPUTE_INPUT_CNTL */ ++ 0x00000000, /* SPI_COMPUTE_NUM_THREAD_X */ ++ 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Y */ ++ 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Z */ ++ 0x00000000, /* SPI_GPR_MGMT */ ++ 0x00000000, /* SPI_LDS_MGMT */ ++ 0x00000000, /* SPI_STACK_MGMT */ ++ 0x00000000, /* SPI_WAVE_MGMT_1 */ ++ 0x00000000, /* SPI_WAVE_MGMT_2 */ ++ ++ 0xc0016900, ++ 0x000001e0, ++ 0x00000000, /* CB_BLEND0_CONTROL */ ++ ++ 0xc00e6900, ++ 0x00000200, ++ 0x00000000, /* DB_DEPTH_CONTROL */ ++ 0x00000000, /* DB_EQAA */ ++ 0x00cc0010, /* CB_COLOR_CONTROL */ ++ 0x00000210, /* DB_SHADER_CONTROL */ ++ 0x00010000, /* PA_CL_CLIP_CNTL */ ++ 0x00000004, /* PA_SU_SC_MODE_CNTL */ ++ 0x00000100, /* PA_CL_VTE_CNTL */ ++ 0x00000000, /* PA_CL_VS_OUT_CNTL */ ++ 0x00000000, /* PA_CL_NANINF_CNTL */ ++ 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ ++ 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ ++ 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ ++ 0x00000000, /* */ ++ 0x00000000, /* */ ++ ++ 0xc0026900, ++ 0x00000229, ++ 0x00000000, /* SQ_PGM_START_FS */ ++ 0x00000000, ++ ++ 0xc0016900, ++ 0x0000023b, ++ 0x00000000, /* SQ_LDS_ALLOC_PS */ ++ ++ 0xc0066900, ++ 0x00000240, ++ 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ ++ 0xc0046900, ++ 0x00000247, ++ 0x00000000, /* SQ_GS_VERT_ITEMSIZE */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ ++ 0xc0116900, ++ 0x00000280, ++ 0x00000000, /* PA_SU_POINT_SIZE */ ++ 0x00000000, /* PA_SU_POINT_MINMAX */ ++ 0x00000008, /* PA_SU_LINE_CNTL */ ++ 0x00000000, /* PA_SC_LINE_STIPPLE */ ++ 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ ++ 0x00000000, /* VGT_HOS_CNTL */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, /* VGT_GS_MODE */ ++ ++ 0xc0026900, ++ 0x00000292, ++ 0x00000000, /* PA_SC_MODE_CNTL_0 */ ++ 0x00000000, /* PA_SC_MODE_CNTL_1 */ ++ ++ 0xc0016900, ++ 0x000002a1, ++ 0x00000000, /* VGT_PRIMITIVEID_EN */ ++ ++ 0xc0016900, ++ 0x000002a5, ++ 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ ++ ++ 0xc0026900, ++ 0x000002a8, ++ 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ ++ 0x00000000, ++ ++ 0xc0026900, ++ 0x000002ad, ++ 0x00000000, /* VGT_REUSE_OFF */ ++ 0x00000000, ++ ++ 0xc0016900, ++ 0x000002d5, ++ 0x00000000, /* VGT_SHADER_STAGES_EN */ ++ ++ 0xc0016900, ++ 0x000002dc, ++ 0x0000aa00, /* DB_ALPHA_TO_MASK */ ++ ++ 0xc0066900, ++ 0x000002de, ++ 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ ++ 0xc0026900, ++ 0x000002e5, ++ 0x00000000, /* VGT_STRMOUT_CONFIG */ ++ 0x00000000, ++ ++ 0xc01b6900, ++ 0x000002f5, ++ 0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */ ++ 0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */ ++ 0x00000000, /* PA_SC_LINE_CNTL */ ++ 0x00000000, /* PA_SC_AA_CONFIG */ ++ 0x00000005, /* PA_SU_VTX_CNTL */ ++ 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ ++ 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ ++ 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ ++ 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ ++ 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0x00000000, ++ 0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */ ++ 0xffffffff, ++ ++ 0xc0026900, ++ 0x00000316, ++ 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ ++ 0x00000010, /* */ ++}; ++ ++const u32 cayman_vs[] = ++{ ++ 0x00000004, ++ 0x80400400, ++ 0x0000a03c, ++ 0x95000688, ++ 0x00004000, ++ 0x15000688, ++ 0x00000000, ++ 0x88000000, ++ 0x04000000, ++ 0x67961001, ++#ifdef __BIG_ENDIAN ++ 0x00020000, ++#else ++ 0x00000000, ++#endif ++ 0x00000000, ++ 0x04000000, ++ 0x67961000, ++#ifdef __BIG_ENDIAN ++ 0x00020008, ++#else ++ 0x00000008, ++#endif ++ 0x00000000, ++}; ++ ++const u32 cayman_ps[] = ++{ ++ 0x00000004, ++ 0xa00c0000, ++ 0x00000008, ++ 0x80400000, ++ 0x00000000, ++ 0x95000688, ++ 0x00000000, ++ 0x88000000, ++ 0x00380400, ++ 0x00146b10, ++ 0x00380000, ++ 0x20146b10, ++ 0x00380400, ++ 0x40146b00, ++ 0x80380000, ++ 0x60146b00, ++ 0x00000010, ++ 0x000d1000, ++ 0xb0800000, ++ 0x00000000, + }; + ++const u32 cayman_ps_size = ARRAY_SIZE(cayman_ps); ++const u32 cayman_vs_size = ARRAY_SIZE(cayman_vs); + const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state); +diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.h b/drivers/gpu/drm/radeon/cayman_blit_shaders.h +index 33b75e5..f5d0e9a 100644 +--- a/drivers/gpu/drm/radeon/cayman_blit_shaders.h ++++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.h +@@ -25,8 +25,11 @@ + #ifndef CAYMAN_BLIT_SHADERS_H + #define CAYMAN_BLIT_SHADERS_H + ++extern const u32 cayman_ps[]; ++extern const u32 cayman_vs[]; + extern const u32 cayman_default_state[]; + ++extern const u32 cayman_ps_size, cayman_vs_size; + extern const u32 cayman_default_size; + + #endif +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index f7e0376..1b583f8 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -88,21 +88,39 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) + /* get temperature in millidegrees */ + int evergreen_get_temp(struct radeon_device *rdev) + { +- u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> +- ASIC_T_SHIFT; +- u32 actual_temp = 0; +- +- if (temp & 0x400) +- actual_temp = -256; +- else if (temp & 0x200) +- actual_temp = 255; +- else if (temp & 0x100) { +- actual_temp = temp & 0x1ff; +- actual_temp |= ~0x1ff; +- } else +- actual_temp = temp & 0xff; ++ u32 temp, toffset, actual_temp = 0; ++ ++ if (rdev->family == CHIP_JUNIPER) { ++ toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> ++ TOFFSET_SHIFT; ++ temp = (RREG32(CG_TS0_STATUS) & TS0_ADC_DOUT_MASK) >> ++ TS0_ADC_DOUT_SHIFT; ++ ++ if (toffset & 0x100) ++ actual_temp = temp / 2 - (0x200 - toffset); ++ else ++ actual_temp = temp / 2 + toffset; ++ ++ actual_temp = actual_temp * 1000; ++ ++ } else { ++ temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> ++ ASIC_T_SHIFT; ++ ++ if (temp & 0x400) ++ actual_temp = -256; ++ else if (temp & 0x200) ++ actual_temp = 255; ++ else if (temp & 0x100) { ++ actual_temp = temp & 0x1ff; ++ actual_temp |= ~0x1ff; ++ } else ++ actual_temp = temp & 0xff; + +- return (actual_temp * 1000) / 2; ++ actual_temp = (actual_temp * 1000) / 2; ++ } ++ ++ return actual_temp; + } + + int sumo_get_temp(struct radeon_device *rdev) +@@ -1578,7 +1596,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) + u32 sq_stack_resource_mgmt_2; + u32 sq_stack_resource_mgmt_3; + u32 vgt_cache_invalidation; +- u32 hdp_host_path_cntl; ++ u32 hdp_host_path_cntl, tmp; + int i, j, num_shader_engines, ps_thread_count; + + switch (rdev->family) { +@@ -1780,7 +1798,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev) + + + mc_shared_chmap = RREG32(MC_SHARED_CHMAP); +- mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); ++ if (rdev->flags & RADEON_IS_IGP) ++ mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG); ++ else ++ mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + + switch (rdev->config.evergreen.max_tile_pipes) { + case 1: +@@ -1933,8 +1954,12 @@ static void evergreen_gpu_init(struct radeon_device *rdev) + rdev->config.evergreen.tile_config |= (3 << 0); + break; + } +- rdev->config.evergreen.tile_config |= +- ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; ++ /* num banks is 8 on all fusion asics */ ++ if (rdev->flags & RADEON_IS_IGP) ++ rdev->config.evergreen.tile_config |= 8 << 4; ++ else ++ rdev->config.evergreen.tile_config |= ++ ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; + rdev->config.evergreen.tile_config |= +@@ -2138,6 +2163,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev) + for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) + WREG32(i, 0); + ++ tmp = RREG32(HDP_MISC_CNTL); ++ tmp |= HDP_FLUSH_INVALIDATE_CACHE; ++ WREG32(HDP_MISC_CNTL, tmp); ++ + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + +diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c +index 2be698e..9c91468 100644 +--- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c ++++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c +@@ -31,6 +31,7 @@ + + #include "evergreend.h" + #include "evergreen_blit_shaders.h" ++#include "cayman_blit_shaders.h" + + #define DI_PT_RECTLIST 0x11 + #define DI_INDEX_SIZE_16_BIT 0x0 +@@ -199,6 +200,16 @@ static void + set_scissors(struct radeon_device *rdev, int x1, int y1, + int x2, int y2) + { ++ /* workaround some hw bugs */ ++ if (x2 == 0) ++ x1 = 1; ++ if (y2 == 0) ++ y1 = 1; ++ if (rdev->family == CHIP_CAYMAN) { ++ if ((x2 == 1) && (y2 == 1)) ++ x2 = 2; ++ } ++ + radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(rdev, (x1 << 0) | (y1 << 16)); +@@ -255,238 +266,240 @@ set_default_state(struct radeon_device *rdev) + u64 gpu_addr; + int dwords; + +- switch (rdev->family) { +- case CHIP_CEDAR: +- default: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 96; +- num_vs_threads = 16; +- num_gs_threads = 16; +- num_es_threads = 16; +- num_hs_threads = 16; +- num_ls_threads = 16; +- num_ps_stack_entries = 42; +- num_vs_stack_entries = 42; +- num_gs_stack_entries = 42; +- num_es_stack_entries = 42; +- num_hs_stack_entries = 42; +- num_ls_stack_entries = 42; +- break; +- case CHIP_REDWOOD: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 128; +- num_vs_threads = 20; +- num_gs_threads = 20; +- num_es_threads = 20; +- num_hs_threads = 20; +- num_ls_threads = 20; +- num_ps_stack_entries = 42; +- num_vs_stack_entries = 42; +- num_gs_stack_entries = 42; +- num_es_stack_entries = 42; +- num_hs_stack_entries = 42; +- num_ls_stack_entries = 42; +- break; +- case CHIP_JUNIPER: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 128; +- num_vs_threads = 20; +- num_gs_threads = 20; +- num_es_threads = 20; +- num_hs_threads = 20; +- num_ls_threads = 20; +- num_ps_stack_entries = 85; +- num_vs_stack_entries = 85; +- num_gs_stack_entries = 85; +- num_es_stack_entries = 85; +- num_hs_stack_entries = 85; +- num_ls_stack_entries = 85; +- break; +- case CHIP_CYPRESS: +- case CHIP_HEMLOCK: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 128; +- num_vs_threads = 20; +- num_gs_threads = 20; +- num_es_threads = 20; +- num_hs_threads = 20; +- num_ls_threads = 20; +- num_ps_stack_entries = 85; +- num_vs_stack_entries = 85; +- num_gs_stack_entries = 85; +- num_es_stack_entries = 85; +- num_hs_stack_entries = 85; +- num_ls_stack_entries = 85; +- break; +- case CHIP_PALM: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 96; +- num_vs_threads = 16; +- num_gs_threads = 16; +- num_es_threads = 16; +- num_hs_threads = 16; +- num_ls_threads = 16; +- num_ps_stack_entries = 42; +- num_vs_stack_entries = 42; +- num_gs_stack_entries = 42; +- num_es_stack_entries = 42; +- num_hs_stack_entries = 42; +- num_ls_stack_entries = 42; +- break; +- case CHIP_BARTS: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 128; +- num_vs_threads = 20; +- num_gs_threads = 20; +- num_es_threads = 20; +- num_hs_threads = 20; +- num_ls_threads = 20; +- num_ps_stack_entries = 85; +- num_vs_stack_entries = 85; +- num_gs_stack_entries = 85; +- num_es_stack_entries = 85; +- num_hs_stack_entries = 85; +- num_ls_stack_entries = 85; +- break; +- case CHIP_TURKS: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 128; +- num_vs_threads = 20; +- num_gs_threads = 20; +- num_es_threads = 20; +- num_hs_threads = 20; +- num_ls_threads = 20; +- num_ps_stack_entries = 42; +- num_vs_stack_entries = 42; +- num_gs_stack_entries = 42; +- num_es_stack_entries = 42; +- num_hs_stack_entries = 42; +- num_ls_stack_entries = 42; +- break; +- case CHIP_CAICOS: +- num_ps_gprs = 93; +- num_vs_gprs = 46; +- num_temp_gprs = 4; +- num_gs_gprs = 31; +- num_es_gprs = 31; +- num_hs_gprs = 23; +- num_ls_gprs = 23; +- num_ps_threads = 128; +- num_vs_threads = 10; +- num_gs_threads = 10; +- num_es_threads = 10; +- num_hs_threads = 10; +- num_ls_threads = 10; +- num_ps_stack_entries = 42; +- num_vs_stack_entries = 42; +- num_gs_stack_entries = 42; +- num_es_stack_entries = 42; +- num_hs_stack_entries = 42; +- num_ls_stack_entries = 42; +- break; +- } +- +- if ((rdev->family == CHIP_CEDAR) || +- (rdev->family == CHIP_PALM) || +- (rdev->family == CHIP_CAICOS)) +- sq_config = 0; +- else +- sq_config = VC_ENABLE; +- +- sq_config |= (EXPORT_SRC_C | +- CS_PRIO(0) | +- LS_PRIO(0) | +- HS_PRIO(0) | +- PS_PRIO(0) | +- VS_PRIO(1) | +- GS_PRIO(2) | +- ES_PRIO(3)); +- +- sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | +- NUM_VS_GPRS(num_vs_gprs) | +- NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); +- sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | +- NUM_ES_GPRS(num_es_gprs)); +- sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | +- NUM_LS_GPRS(num_ls_gprs)); +- sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | +- NUM_VS_THREADS(num_vs_threads) | +- NUM_GS_THREADS(num_gs_threads) | +- NUM_ES_THREADS(num_es_threads)); +- sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | +- NUM_LS_THREADS(num_ls_threads)); +- sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | +- NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); +- sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | +- NUM_ES_STACK_ENTRIES(num_es_stack_entries)); +- sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | +- NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); +- + /* set clear context state */ + radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); + radeon_ring_write(rdev, 0); + +- /* disable dyn gprs */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +- radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); +- radeon_ring_write(rdev, 0); ++ if (rdev->family < CHIP_CAYMAN) { ++ switch (rdev->family) { ++ case CHIP_CEDAR: ++ default: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 96; ++ num_vs_threads = 16; ++ num_gs_threads = 16; ++ num_es_threads = 16; ++ num_hs_threads = 16; ++ num_ls_threads = 16; ++ num_ps_stack_entries = 42; ++ num_vs_stack_entries = 42; ++ num_gs_stack_entries = 42; ++ num_es_stack_entries = 42; ++ num_hs_stack_entries = 42; ++ num_ls_stack_entries = 42; ++ break; ++ case CHIP_REDWOOD: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 128; ++ num_vs_threads = 20; ++ num_gs_threads = 20; ++ num_es_threads = 20; ++ num_hs_threads = 20; ++ num_ls_threads = 20; ++ num_ps_stack_entries = 42; ++ num_vs_stack_entries = 42; ++ num_gs_stack_entries = 42; ++ num_es_stack_entries = 42; ++ num_hs_stack_entries = 42; ++ num_ls_stack_entries = 42; ++ break; ++ case CHIP_JUNIPER: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 128; ++ num_vs_threads = 20; ++ num_gs_threads = 20; ++ num_es_threads = 20; ++ num_hs_threads = 20; ++ num_ls_threads = 20; ++ num_ps_stack_entries = 85; ++ num_vs_stack_entries = 85; ++ num_gs_stack_entries = 85; ++ num_es_stack_entries = 85; ++ num_hs_stack_entries = 85; ++ num_ls_stack_entries = 85; ++ break; ++ case CHIP_CYPRESS: ++ case CHIP_HEMLOCK: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 128; ++ num_vs_threads = 20; ++ num_gs_threads = 20; ++ num_es_threads = 20; ++ num_hs_threads = 20; ++ num_ls_threads = 20; ++ num_ps_stack_entries = 85; ++ num_vs_stack_entries = 85; ++ num_gs_stack_entries = 85; ++ num_es_stack_entries = 85; ++ num_hs_stack_entries = 85; ++ num_ls_stack_entries = 85; ++ break; ++ case CHIP_PALM: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 96; ++ num_vs_threads = 16; ++ num_gs_threads = 16; ++ num_es_threads = 16; ++ num_hs_threads = 16; ++ num_ls_threads = 16; ++ num_ps_stack_entries = 42; ++ num_vs_stack_entries = 42; ++ num_gs_stack_entries = 42; ++ num_es_stack_entries = 42; ++ num_hs_stack_entries = 42; ++ num_ls_stack_entries = 42; ++ break; ++ case CHIP_BARTS: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 128; ++ num_vs_threads = 20; ++ num_gs_threads = 20; ++ num_es_threads = 20; ++ num_hs_threads = 20; ++ num_ls_threads = 20; ++ num_ps_stack_entries = 85; ++ num_vs_stack_entries = 85; ++ num_gs_stack_entries = 85; ++ num_es_stack_entries = 85; ++ num_hs_stack_entries = 85; ++ num_ls_stack_entries = 85; ++ break; ++ case CHIP_TURKS: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 128; ++ num_vs_threads = 20; ++ num_gs_threads = 20; ++ num_es_threads = 20; ++ num_hs_threads = 20; ++ num_ls_threads = 20; ++ num_ps_stack_entries = 42; ++ num_vs_stack_entries = 42; ++ num_gs_stack_entries = 42; ++ num_es_stack_entries = 42; ++ num_hs_stack_entries = 42; ++ num_ls_stack_entries = 42; ++ break; ++ case CHIP_CAICOS: ++ num_ps_gprs = 93; ++ num_vs_gprs = 46; ++ num_temp_gprs = 4; ++ num_gs_gprs = 31; ++ num_es_gprs = 31; ++ num_hs_gprs = 23; ++ num_ls_gprs = 23; ++ num_ps_threads = 128; ++ num_vs_threads = 10; ++ num_gs_threads = 10; ++ num_es_threads = 10; ++ num_hs_threads = 10; ++ num_ls_threads = 10; ++ num_ps_stack_entries = 42; ++ num_vs_stack_entries = 42; ++ num_gs_stack_entries = 42; ++ num_es_stack_entries = 42; ++ num_hs_stack_entries = 42; ++ num_ls_stack_entries = 42; ++ break; ++ } + +- /* SQ config */ +- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); +- radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); +- radeon_ring_write(rdev, sq_config); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); +- radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, 0); +- radeon_ring_write(rdev, sq_thread_resource_mgmt); +- radeon_ring_write(rdev, sq_thread_resource_mgmt_2); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_1); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_2); +- radeon_ring_write(rdev, sq_stack_resource_mgmt_3); ++ if ((rdev->family == CHIP_CEDAR) || ++ (rdev->family == CHIP_PALM) || ++ (rdev->family == CHIP_CAICOS)) ++ sq_config = 0; ++ else ++ sq_config = VC_ENABLE; ++ ++ sq_config |= (EXPORT_SRC_C | ++ CS_PRIO(0) | ++ LS_PRIO(0) | ++ HS_PRIO(0) | ++ PS_PRIO(0) | ++ VS_PRIO(1) | ++ GS_PRIO(2) | ++ ES_PRIO(3)); ++ ++ sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | ++ NUM_VS_GPRS(num_vs_gprs) | ++ NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); ++ sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | ++ NUM_ES_GPRS(num_es_gprs)); ++ sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | ++ NUM_LS_GPRS(num_ls_gprs)); ++ sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | ++ NUM_VS_THREADS(num_vs_threads) | ++ NUM_GS_THREADS(num_gs_threads) | ++ NUM_ES_THREADS(num_es_threads)); ++ sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | ++ NUM_LS_THREADS(num_ls_threads)); ++ sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | ++ NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); ++ sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | ++ NUM_ES_STACK_ENTRIES(num_es_stack_entries)); ++ sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | ++ NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); ++ ++ /* disable dyn gprs */ ++ radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); ++ radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(rdev, 0); ++ ++ /* SQ config */ ++ radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); ++ radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); ++ radeon_ring_write(rdev, sq_config); ++ radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); ++ radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); ++ radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); ++ radeon_ring_write(rdev, 0); ++ radeon_ring_write(rdev, 0); ++ radeon_ring_write(rdev, sq_thread_resource_mgmt); ++ radeon_ring_write(rdev, sq_thread_resource_mgmt_2); ++ radeon_ring_write(rdev, sq_stack_resource_mgmt_1); ++ radeon_ring_write(rdev, sq_stack_resource_mgmt_2); ++ radeon_ring_write(rdev, sq_stack_resource_mgmt_3); ++ } + + /* CONTEXT_CONTROL */ + radeon_ring_write(rdev, 0xc0012800); +@@ -560,7 +573,10 @@ int evergreen_blit_init(struct radeon_device *rdev) + mutex_init(&rdev->r600_blit.mutex); + rdev->r600_blit.state_offset = 0; + +- rdev->r600_blit.state_len = evergreen_default_size; ++ if (rdev->family < CHIP_CAYMAN) ++ rdev->r600_blit.state_len = evergreen_default_size; ++ else ++ rdev->r600_blit.state_len = cayman_default_size; + + dwords = rdev->r600_blit.state_len; + while (dwords & 0xf) { +@@ -572,11 +588,17 @@ int evergreen_blit_init(struct radeon_device *rdev) + obj_size = ALIGN(obj_size, 256); + + rdev->r600_blit.vs_offset = obj_size; +- obj_size += evergreen_vs_size * 4; ++ if (rdev->family < CHIP_CAYMAN) ++ obj_size += evergreen_vs_size * 4; ++ else ++ obj_size += cayman_vs_size * 4; + obj_size = ALIGN(obj_size, 256); + + rdev->r600_blit.ps_offset = obj_size; +- obj_size += evergreen_ps_size * 4; ++ if (rdev->family < CHIP_CAYMAN) ++ obj_size += evergreen_ps_size * 4; ++ else ++ obj_size += cayman_ps_size * 4; + obj_size = ALIGN(obj_size, 256); + + r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, +@@ -599,16 +621,29 @@ int evergreen_blit_init(struct radeon_device *rdev) + return r; + } + +- memcpy_toio(ptr + rdev->r600_blit.state_offset, +- evergreen_default_state, rdev->r600_blit.state_len * 4); +- +- if (num_packet2s) +- memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), +- packet2s, num_packet2s * 4); +- for (i = 0; i < evergreen_vs_size; i++) +- *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]); +- for (i = 0; i < evergreen_ps_size; i++) +- *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]); ++ if (rdev->family < CHIP_CAYMAN) { ++ memcpy_toio(ptr + rdev->r600_blit.state_offset, ++ evergreen_default_state, rdev->r600_blit.state_len * 4); ++ ++ if (num_packet2s) ++ memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), ++ packet2s, num_packet2s * 4); ++ for (i = 0; i < evergreen_vs_size; i++) ++ *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]); ++ for (i = 0; i < evergreen_ps_size; i++) ++ *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]); ++ } else { ++ memcpy_toio(ptr + rdev->r600_blit.state_offset, ++ cayman_default_state, rdev->r600_blit.state_len * 4); ++ ++ if (num_packet2s) ++ memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), ++ packet2s, num_packet2s * 4); ++ for (i = 0; i < cayman_vs_size; i++) ++ *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(cayman_vs[i]); ++ for (i = 0; i < cayman_ps_size; i++) ++ *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(cayman_ps[i]); ++ } + radeon_bo_kunmap(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + +diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h +index 9453384..1636e34 100644 +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -64,6 +64,8 @@ + #define GB_BACKEND_MAP 0x98FC + #define DMIF_ADDR_CONFIG 0xBD4 + #define HDP_ADDR_CONFIG 0x2F48 ++#define HDP_MISC_CNTL 0x2F4C ++#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) + + #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 + #define GC_USER_RB_BACKEND_DISABLE 0x9B7C +@@ -166,10 +168,16 @@ + #define SE_DB_BUSY (1 << 30) + #define SE_CB_BUSY (1 << 31) + /* evergreen */ ++#define CG_THERMAL_CTRL 0x72c ++#define TOFFSET_MASK 0x00003FE0 ++#define TOFFSET_SHIFT 5 + #define CG_MULT_THERMAL_STATUS 0x740 + #define ASIC_T(x) ((x) << 16) +-#define ASIC_T_MASK 0x7FF0000 ++#define ASIC_T_MASK 0x07FF0000 + #define ASIC_T_SHIFT 16 ++#define CG_TS0_STATUS 0x760 ++#define TS0_ADC_DOUT_MASK 0x000003FF ++#define TS0_ADC_DOUT_SHIFT 0 + /* APU */ + #define CG_THERMAL_STATUS 0x678 + +@@ -200,6 +208,7 @@ + #define BURSTLENGTH_SHIFT 9 + #define BURSTLENGTH_MASK 0x00000200 + #define CHANSIZE_OVERRIDE (1 << 11) ++#define FUS_MC_ARB_RAMCFG 0x2768 + #define MC_VM_AGP_TOP 0x2028 + #define MC_VM_AGP_BOT 0x202C + #define MC_VM_AGP_BASE 0x2030 +diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c +index 8c199c4..b226cca 100644 +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -417,7 +417,7 @@ static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + num_shader_engines = 1; + if (num_shader_engines > rdev->config.cayman.max_shader_engines) + num_shader_engines = rdev->config.cayman.max_shader_engines; +- if (num_backends_per_asic > num_shader_engines) ++ if (num_backends_per_asic < num_shader_engines) + num_backends_per_asic = num_shader_engines; + if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) + num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; +@@ -674,7 +674,7 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); + cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); +- cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE); ++ cgts_tcc_disable = 0xff000000; + gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); + gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); + cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); +@@ -829,7 +829,7 @@ static void cayman_gpu_init(struct radeon_device *rdev) + rdev->config.cayman.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; + rdev->config.cayman.tile_config |= +- (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; ++ ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; + rdev->config.cayman.tile_config |= + ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; + +@@ -871,7 +871,7 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + smx_dc_ctl0 = RREG32(SMX_DC_CTL0); + smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); +- smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); ++ smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets); + WREG32(SMX_DC_CTL0, smx_dc_ctl0); + + WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE); +@@ -887,20 +887,20 @@ static void cayman_gpu_init(struct radeon_device *rdev) + + WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO); + +- WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | +- POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | +- SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); ++ WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) | ++ POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) | ++ SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1))); + +- WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) | +- SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) | +- SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size))); ++ WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) | ++ SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) | ++ SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size))); + + + WREG32(VGT_NUM_INSTANCES, 1); + + WREG32(CP_PERFMON_CNTL, 0); + +- WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) | ++ WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) | + FETCH_FIFO_HIWATER(0x4) | + DONE_FIFO_HIWATER(0xe0) | + ALU_UPDATE_FIFO_HIWATER(0x8))); +@@ -931,6 +931,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) + WREG32(CB_PERF_CTR3_SEL_0, 0); + WREG32(CB_PERF_CTR3_SEL_1, 0); + ++ tmp = RREG32(HDP_MISC_CNTL); ++ tmp |= HDP_FLUSH_INVALIDATE_CACHE; ++ WREG32(HDP_MISC_CNTL, tmp); ++ + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + +@@ -1383,14 +1387,12 @@ static int cayman_startup(struct radeon_device *rdev) + return r; + cayman_gpu_init(rdev); + +-#if 0 +- r = cayman_blit_init(rdev); ++ r = evergreen_blit_init(rdev); + if (r) { +- cayman_blit_fini(rdev); ++ evergreen_blit_fini(rdev); + rdev->asic->copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } +-#endif + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); +@@ -1448,7 +1450,7 @@ int cayman_resume(struct radeon_device *rdev) + + int cayman_suspend(struct radeon_device *rdev) + { +- /* int r; */ ++ int r; + + /* FIXME: we should wait for ring to be empty */ + cayman_cp_enable(rdev, false); +@@ -1457,14 +1459,13 @@ int cayman_suspend(struct radeon_device *rdev) + radeon_wb_disable(rdev); + cayman_pcie_gart_disable(rdev); + +-#if 0 + /* unpin shaders bo */ + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (likely(r == 0)) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + } +-#endif ++ + return 0; + } + +@@ -1576,7 +1577,7 @@ int cayman_init(struct radeon_device *rdev) + + void cayman_fini(struct radeon_device *rdev) + { +- /* cayman_blit_fini(rdev); */ ++ evergreen_blit_fini(rdev); + cayman_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); +diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h +index 0f9a08b..9736746 100644 +--- a/drivers/gpu/drm/radeon/nid.h ++++ b/drivers/gpu/drm/radeon/nid.h +@@ -136,6 +136,8 @@ + #define HDP_NONSURFACE_INFO 0x2C08 + #define HDP_NONSURFACE_SIZE 0x2C0C + #define HDP_ADDR_CONFIG 0x2F48 ++#define HDP_MISC_CNTL 0x2F4C ++#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) + + #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 + #define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C +@@ -351,7 +353,7 @@ + #define MULTI_GPU_TILE_SIZE_MASK 0x03000000 + #define MULTI_GPU_TILE_SIZE_SHIFT 24 + #define ROW_SIZE(x) ((x) << 28) +-#define ROW_SIZE_MASK 0x30000007 ++#define ROW_SIZE_MASK 0x30000000 + #define ROW_SIZE_SHIFT 28 + #define NUM_LOWER_PIPES(x) ((x) << 30) + #define NUM_LOWER_PIPES_MASK 0x40000000 +diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +index ca57619..b9b3c2a 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -782,6 +782,7 @@ static struct radeon_asic evergreen_asic = { + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, +@@ -828,6 +829,7 @@ static struct radeon_asic sumo_asic = { + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, +@@ -874,6 +876,7 @@ static struct radeon_asic btc_asic = { + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, +@@ -903,9 +906,9 @@ static struct radeon_asic cayman_asic = { + .get_vblank_counter = &evergreen_get_vblank_counter, + .fence_ring_emit = &r600_fence_ring_emit, + .cs_parse = &evergreen_cs_parse, +- .copy_blit = NULL, +- .copy_dma = NULL, +- .copy = NULL, ++ .copy_blit = &evergreen_copy_blit, ++ .copy_dma = &evergreen_copy_blit, ++ .copy = &evergreen_copy_blit, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = &radeon_atom_get_memory_clock, +@@ -920,6 +923,7 @@ static struct radeon_asic cayman_asic = { + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, +diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c +index ed5dfe5..9d95792 100644 +--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c ++++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c +@@ -15,6 +15,9 @@ + #define ATPX_VERSION 0 + #define ATPX_GPU_PWR 2 + #define ATPX_MUX_SELECT 3 ++#define ATPX_I2C_MUX_SELECT 4 ++#define ATPX_SWITCH_START 5 ++#define ATPX_SWITCH_END 6 + + #define ATPX_INTEGRATED 0 + #define ATPX_DISCRETE 1 +@@ -149,13 +152,35 @@ static int radeon_atpx_switch_mux(acpi_handle handle, int mux_id) + return radeon_atpx_execute(handle, ATPX_MUX_SELECT, mux_id); + } + ++static int radeon_atpx_switch_i2c_mux(acpi_handle handle, int mux_id) ++{ ++ return radeon_atpx_execute(handle, ATPX_I2C_MUX_SELECT, mux_id); ++} ++ ++static int radeon_atpx_switch_start(acpi_handle handle, int gpu_id) ++{ ++ return radeon_atpx_execute(handle, ATPX_SWITCH_START, gpu_id); ++} ++ ++static int radeon_atpx_switch_end(acpi_handle handle, int gpu_id) ++{ ++ return radeon_atpx_execute(handle, ATPX_SWITCH_END, gpu_id); ++} + + static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) + { ++ int gpu_id; ++ + if (id == VGA_SWITCHEROO_IGD) +- radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 0); ++ gpu_id = ATPX_INTEGRATED; + else +- radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 1); ++ gpu_id = ATPX_DISCRETE; ++ ++ radeon_atpx_switch_start(radeon_atpx_priv.atpx_handle, gpu_id); ++ radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, gpu_id); ++ radeon_atpx_switch_i2c_mux(radeon_atpx_priv.atpx_handle, gpu_id); ++ radeon_atpx_switch_end(radeon_atpx_priv.atpx_handle, gpu_id); ++ + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c +index 8caf546..089ab92 100644 +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -2504,6 +2504,12 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) + return true; + } + ++static const char *thermal_controller_names[] = { ++ "NONE", ++ "lm63", ++ "adm1032", ++}; ++ + void radeon_combios_get_power_modes(struct radeon_device *rdev) + { + struct drm_device *dev = rdev->ddev; +@@ -2524,6 +2530,54 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) + return; + } + ++ /* check for a thermal chip */ ++ offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE); ++ if (offset) { ++ u8 thermal_controller = 0, gpio = 0, i2c_addr = 0, clk_bit = 0, data_bit = 0; ++ struct radeon_i2c_bus_rec i2c_bus; ++ ++ rev = RBIOS8(offset); ++ ++ if (rev == 0) { ++ thermal_controller = RBIOS8(offset + 3); ++ gpio = RBIOS8(offset + 4) & 0x3f; ++ i2c_addr = RBIOS8(offset + 5); ++ } else if (rev == 1) { ++ thermal_controller = RBIOS8(offset + 4); ++ gpio = RBIOS8(offset + 5) & 0x3f; ++ i2c_addr = RBIOS8(offset + 6); ++ } else if (rev == 2) { ++ thermal_controller = RBIOS8(offset + 4); ++ gpio = RBIOS8(offset + 5) & 0x3f; ++ i2c_addr = RBIOS8(offset + 6); ++ clk_bit = RBIOS8(offset + 0xa); ++ data_bit = RBIOS8(offset + 0xb); ++ } ++ if ((thermal_controller > 0) && (thermal_controller < 3)) { ++ DRM_INFO("Possible %s thermal controller at 0x%02x\n", ++ thermal_controller_names[thermal_controller], ++ i2c_addr >> 1); ++ if (gpio == DDC_LCD) { ++ /* MM i2c */ ++ i2c_bus.valid = true; ++ i2c_bus.hw_capable = true; ++ i2c_bus.mm_i2c = true; ++ i2c_bus.i2c_id = 0xa0; ++ } else if (gpio == DDC_GPIO) ++ i2c_bus = combios_setup_i2c_bus(rdev, gpio, 1 << clk_bit, 1 << data_bit); ++ else ++ i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); ++ rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); ++ if (rdev->pm.i2c_bus) { ++ struct i2c_board_info info = { }; ++ const char *name = thermal_controller_names[thermal_controller]; ++ info.addr = i2c_addr >> 1; ++ strlcpy(info.type, name, sizeof(info.type)); ++ i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); ++ } ++ } ++ } ++ + if (rdev->flags & RADEON_IS_MOBILITY) { + offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); + if (offset) { +diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c +index 017ac54..5df2acd 100644 +--- a/drivers/gpu/drm/radeon/radeon_cursor.c ++++ b/drivers/gpu/drm/radeon/radeon_cursor.c +@@ -167,9 +167,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, + return -EINVAL; + } + +- radeon_crtc->cursor_width = width; +- radeon_crtc->cursor_height = height; +- + obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); + if (!obj) { + DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); +@@ -180,6 +177,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, + if (ret) + goto fail; + ++ radeon_crtc->cursor_width = width; ++ radeon_crtc->cursor_height = height; ++ + radeon_lock_cursor(crtc, true); + /* XXX only 27 bit offset for legacy cursor */ + radeon_set_cursor(crtc, obj, gpu_addr); +diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c +index 0444911..fc44376 100644 +--- a/drivers/gpu/drm/radeon/radeon_drv.c ++++ b/drivers/gpu/drm/radeon/radeon_drv.c +@@ -50,9 +50,10 @@ + * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs + * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query + * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query ++ * 2.10.0 - fusion 2D tiling + */ + #define KMS_DRIVER_MAJOR 2 +-#define KMS_DRIVER_MINOR 9 ++#define KMS_DRIVER_MINOR 10 + #define KMS_DRIVER_PATCHLEVEL 0 + int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); + int radeon_driver_unload_kms(struct drm_device *dev); +diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c +index 320ddc3..4fec348 100644 +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -485,6 +485,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev) + case THERMAL_TYPE_RV6XX: + case THERMAL_TYPE_RV770: + case THERMAL_TYPE_EVERGREEN: ++ case THERMAL_TYPE_NI: + case THERMAL_TYPE_SUMO: + rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); + if (IS_ERR(rdev->pm.int_hwmon_dev)) { +diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman +index 6334f8a..0aa8e85 100644 +--- a/drivers/gpu/drm/radeon/reg_srcs/cayman ++++ b/drivers/gpu/drm/radeon/reg_srcs/cayman +@@ -33,6 +33,7 @@ cayman 0x9400 + 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS + 0x00009100 SPI_CONFIG_CNTL + 0x0000913C SPI_CONFIG_CNTL_1 ++0x00009508 TA_CNTL_AUX + 0x00009830 DB_DEBUG + 0x00009834 DB_DEBUG2 + 0x00009838 DB_DEBUG3 +diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen +index 7e16371..0e28cae 100644 +--- a/drivers/gpu/drm/radeon/reg_srcs/evergreen ++++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen +@@ -46,6 +46,7 @@ evergreen 0x9400 + 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS + 0x00009100 SPI_CONFIG_CNTL + 0x0000913C SPI_CONFIG_CNTL_1 ++0x00009508 TA_CNTL_AUX + 0x00009700 VC_CNTL + 0x00009714 VC_ENHANCE + 0x00009830 DB_DEBUG diff --git a/kernel.spec b/kernel.spec index 15b2bc1c0..587ce74f5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -687,6 +687,7 @@ Patch1829: drm-intel-restore-mode.patch # radeon - new hw + fixes for fusion and t500 regression Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch Patch1840: drm-radeon-update.patch +Patch1841: drm-radeon-update2.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1344,6 +1345,7 @@ ApplyPatch drm-intel-restore-mode.patch # radeon DRM (add cayman support) ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -R ApplyPatch drm-radeon-update.patch +ApplyPatch drm-radeon-update2.patch # linux1394 git patches #ApplyPatch linux-2.6-firewire-git-update.patch @@ -2015,6 +2017,9 @@ fi # and build. %changelog +* Wed May 25 2011 Dave Airlie +- drm-radeon-update2.patch: more radeon updates + cayman accel support + * Tue May 24 2011 Kyle McMartin - hid-multitouch: add support for elo touchsystems panels (requested by hadess, backported from hid-next) From 1c2a2024ce742654e469dddfb13232de909a200d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 27 May 2011 14:37:34 +1000 Subject: [PATCH 65/99] nouveau: fixes from upstream for a number of issues --- drm-nouveau-fixes.patch | 167 ------ drm-nouveau-updates.patch | 1013 ++++++++++++++++++++++++++++++++++--- kernel.spec | 8 +- 3 files changed, 946 insertions(+), 242 deletions(-) diff --git a/drm-nouveau-fixes.patch b/drm-nouveau-fixes.patch index d74feb7d2..8b1378917 100644 --- a/drm-nouveau-fixes.patch +++ b/drm-nouveau-fixes.patch @@ -1,168 +1 @@ -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index 982d70b..c01e43f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.h -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -681,6 +681,9 @@ struct drm_nouveau_private { - /* For PFIFO and PGRAPH. */ - spinlock_t context_switch_lock; -+ /* VM/PRAMIN flush, legacy PRAMIN aperture */ -+ spinlock_t vm_lock; -+ - /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ - struct nouveau_ramht *ramht; - struct nouveau_gpuobj *ramfc; -diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c -index 30b6544..2002a43 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_object.c -+++ b/drivers/gpu/drm/nouveau/nouveau_object.c -@@ -1013,19 +1013,20 @@ nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) - { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_device *dev = gpuobj->dev; -+ unsigned long flags; - - if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { - u64 ptr = gpuobj->vinst + offset; - u32 base = ptr >> 16; - u32 val; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - if (dev_priv->ramin_base != base) { - dev_priv->ramin_base = base; - nv_wr32(dev, 0x001700, dev_priv->ramin_base); - } - val = nv_rd32(dev, 0x700000 + (ptr & 0xffff)); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - return val; - } - -@@ -1037,18 +1038,19 @@ nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) - { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_device *dev = gpuobj->dev; -+ unsigned long flags; - - if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { - u64 ptr = gpuobj->vinst + offset; - u32 base = ptr >> 16; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - if (dev_priv->ramin_base != base) { - dev_priv->ramin_base = base; - nv_wr32(dev, 0x001700, dev_priv->ramin_base); - } - nv_wr32(dev, 0x700000 + (ptr & 0xffff), val); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - return; - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index a54fc43..a358dc5 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_state.c -+++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -646,6 +646,7 @@ nouveau_card_init(struct drm_device *dev) - spin_lock_init(&dev_priv->channels.lock); - spin_lock_init(&dev_priv->tile.lock); - spin_lock_init(&dev_priv->context_switch_lock); -+ spin_lock_init(&dev_priv->vm_lock); - - /* Make the CRTCs and I2C buses accessible */ - ret = engine->display.early_init(dev); -diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c -index e57caa2..53a4b40 100644 ---- a/drivers/gpu/drm/nouveau/nv50_instmem.c -+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c -@@ -404,23 +404,25 @@ void - nv50_instmem_flush(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x00330c, 0x00000001); - if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } - - void - nv84_instmem_flush(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x070000, 0x00000001); - if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } - -diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c -index 6144156..248496f 100644 ---- a/drivers/gpu/drm/nouveau/nv50_vm.c -+++ b/drivers/gpu/drm/nouveau/nv50_vm.c -@@ -170,10 +170,11 @@ void - nv50_vm_flush_engine(struct drm_device *dev, int engine) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x100c80, (engine << 16) | 1); - if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) - NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } -diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c -index e4e83c2..10a5a99 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_vm.c -+++ b/drivers/gpu/drm/nouveau/nvc0_vm.c -@@ -104,20 +104,27 @@ nvc0_vm_flush(struct nouveau_vm *vm) - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; - struct drm_device *dev = vm->dev; - struct nouveau_vm_pgd *vpgd; -- u32 r100c80, engine; -+ unsigned long flags; -+ u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; - - pinstmem->flush(vm->dev); - -- if (vm == dev_priv->chan_vm) -- engine = 1; -- else -- engine = 5; -- -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - list_for_each_entry(vpgd, &vm->pgd_list, head) { -- r100c80 = nv_rd32(dev, 0x100c80); -+ /* looks like maybe a "free flush slots" counter, the -+ * faster you write to 0x100cbc to more it decreases -+ */ -+ if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { -+ NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", -+ nv_rd32(dev, 0x100c80), engine); -+ } - nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); - nv_wr32(dev, 0x100cbc, 0x80000000 | engine); -- if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80)) -- NV_ERROR(dev, "vm flush timeout eng %d\n", engine); -+ /* wait for flush to be queued? */ -+ if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { -+ NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", -+ nv_rd32(dev, 0x100c80), engine); -+ } - } -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 60f8d4d64..d0a6bfe53 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,5 +1,5 @@ diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c -index 6bdab89..90aef64 100644 +index 6bdab89..729d5fd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -269,7 +269,7 @@ struct init_tbl_entry { @@ -102,7 +102,20 @@ index 6bdab89..90aef64 100644 } #ifdef __powerpc__ /* Powerbook specific quirks */ -@@ -5950,6 +5971,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) +@@ -5028,11 +5049,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims + pll_lim->vco1.max_n = record[11]; + pll_lim->min_p = record[12]; + pll_lim->max_p = record[13]; +- /* where did this go to?? */ +- if ((entry[0] & 0xf0) == 0x80) +- pll_lim->refclk = 27000; +- else +- pll_lim->refclk = 100000; ++ pll_lim->refclk = ROM16(entry[9]) * 1000; + } + + /* +@@ -5950,6 +5967,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) } } @@ -114,7 +127,7 @@ index 6bdab89..90aef64 100644 static void parse_dcb_connector_table(struct nvbios *bios) { -@@ -5986,23 +6012,9 @@ parse_dcb_connector_table(struct nvbios *bios) +@@ -5986,23 +6008,9 @@ parse_dcb_connector_table(struct nvbios *bios) cte->type = (cte->entry & 0x000000ff) >> 0; cte->index2 = (cte->entry & 0x00000f00) >> 8; @@ -141,7 +154,15 @@ index 6bdab89..90aef64 100644 if (cte->type == 0xff) continue; -@@ -6342,6 +6354,32 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) +@@ -6023,6 +6031,7 @@ parse_dcb_connector_table(struct nvbios *bios) + case DCB_CONNECTOR_DVI_I: + case DCB_CONNECTOR_DVI_D: + case DCB_CONNECTOR_LVDS: ++ case DCB_CONNECTOR_LVDS_SPWG: + case DCB_CONNECTOR_DP: + case DCB_CONNECTOR_eDP: + case DCB_CONNECTOR_HDMI_0: +@@ -6342,6 +6351,32 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) } } @@ -174,7 +195,7 @@ index 6bdab89..90aef64 100644 return true; } -@@ -6702,11 +6740,11 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, +@@ -6702,11 +6737,11 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, struct nvbios *bios = &dev_priv->vbios; struct init_exec iexec = { true, false }; @@ -188,7 +209,7 @@ index 6bdab89..90aef64 100644 } static bool NVInitVBIOS(struct drm_device *dev) -@@ -6715,7 +6753,7 @@ static bool NVInitVBIOS(struct drm_device *dev) +@@ -6715,7 +6750,7 @@ static bool NVInitVBIOS(struct drm_device *dev) struct nvbios *bios = &dev_priv->vbios; memset(bios, 0, sizeof(struct nvbios)); @@ -198,10 +219,18 @@ index 6bdab89..90aef64 100644 if (!NVShadowVBIOS(dev, bios->data)) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h -index 50a648e..8a54fa7 100644 +index 50a648e..050c314 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h -@@ -251,7 +251,7 @@ struct nvbios { +@@ -82,6 +82,7 @@ enum dcb_connector_type { + DCB_CONNECTOR_DVI_I = 0x30, + DCB_CONNECTOR_DVI_D = 0x31, + DCB_CONNECTOR_LVDS = 0x40, ++ DCB_CONNECTOR_LVDS_SPWG = 0x41, + DCB_CONNECTOR_DP = 0x46, + DCB_CONNECTOR_eDP = 0x47, + DCB_CONNECTOR_HDMI_0 = 0x60, +@@ -251,7 +252,7 @@ struct nvbios { uint8_t digital_min_front_porch; bool fp_no_ddc; @@ -716,6 +745,53 @@ index 3960d66..3837090 100644 if (ret) { NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); return NULL; +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c +index 390d82c..084c089 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -438,7 +438,7 @@ nouveau_connector_set_property(struct drm_connector *connector, + } + + /* LVDS always needs gpu scaling */ +- if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS && ++ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS && + value == DRM_MODE_SCALE_NONE) + return -EINVAL; + +@@ -646,6 +646,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) + ret = get_slave_funcs(encoder)->get_modes(encoder, connector); + + if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || ++ nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG || + nv_connector->dcb->type == DCB_CONNECTOR_eDP) + ret += nouveau_connector_scaler_modes_add(connector); + +@@ -806,6 +807,7 @@ nouveau_connector_create(struct drm_device *dev, int index) + type = DRM_MODE_CONNECTOR_HDMIA; + break; + case DCB_CONNECTOR_LVDS: ++ case DCB_CONNECTOR_LVDS_SPWG: + type = DRM_MODE_CONNECTOR_LVDS; + funcs = &nouveau_connector_funcs_lvds; + break; +@@ -834,7 +836,7 @@ nouveau_connector_create(struct drm_device *dev, int index) + drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); + + /* Check if we need dithering enabled */ +- if (dcb->type == DCB_CONNECTOR_LVDS) { ++ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { + bool dummy, is_24bit = false; + + ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit); +@@ -879,7 +881,7 @@ nouveau_connector_create(struct drm_device *dev, int index) + nv_connector->use_dithering ? + DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); + +- if (dcb->type != DCB_CONNECTOR_LVDS) { ++ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) { + if (dev_priv->card_type >= NV_50) + connector->polled = DRM_CONNECTOR_POLL_HPD; + else diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 505c6bf..764c15d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c @@ -852,9 +928,18 @@ index 505c6bf..764c15d 100644 spin_unlock_irqrestore(&dev->event_lock, flags); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c -index b368ed7..ce38e97 100644 +index b368ed7..568caed 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c +@@ -83,7 +83,7 @@ nouveau_dma_init(struct nouveau_channel *chan) + return ret; + + /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ +- ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfd0, 0x1000, ++ ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000, + &chan->m2mf_ntfy); + if (ret) + return ret; @@ -97,13 +97,15 @@ nouveau_dma_init(struct nouveau_channel *chan) OUT_RING(chan, 0); @@ -926,7 +1011,7 @@ index 38d5995..7beb82a 100644 ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index 982d70b..e172d72 100644 +index 982d70b..b260c55 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -57,7 +57,7 @@ struct nouveau_fpriv { @@ -981,7 +1066,15 @@ index 982d70b..e172d72 100644 int (*early_init)(struct drm_device *); void (*late_takedown)(struct drm_device *); int (*create)(struct drm_device *); -@@ -463,6 +466,7 @@ struct nouveau_pm_memtiming { +@@ -433,6 +436,7 @@ struct nouveau_pm_level { + u32 memory; + u32 shader; + u32 unk05; ++ u32 unk0a; + + u8 voltage; + u8 fanspeed; +@@ -463,6 +467,7 @@ struct nouveau_pm_memtiming { u32 reg_100234; u32 reg_100238; u32 reg_10023c; @@ -989,7 +1082,7 @@ index 982d70b..e172d72 100644 }; struct nouveau_pm_memtimings { -@@ -509,8 +513,8 @@ struct nouveau_crypt_engine { +@@ -509,8 +514,8 @@ struct nouveau_crypt_engine { struct nouveau_vram_engine { int (*init)(struct drm_device *); int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, @@ -1000,7 +1093,7 @@ index 982d70b..e172d72 100644 bool (*flags_valid)(struct drm_device *, u32 tile_flags); }; -@@ -634,6 +638,7 @@ struct drm_nouveau_private { +@@ -634,6 +639,7 @@ struct drm_nouveau_private { enum nouveau_card_type card_type; /* exact chipset, derived from NV_PMC_BOOT_0 */ int chipset; @@ -1008,7 +1101,7 @@ index 982d70b..e172d72 100644 int flags; void __iomem *mmio; -@@ -652,8 +657,6 @@ struct drm_nouveau_private { +@@ -652,8 +658,6 @@ struct drm_nouveau_private { /* interrupt handling */ void (*irq_handler[32])(struct drm_device *); bool msi_enabled; @@ -1017,7 +1110,17 @@ index 982d70b..e172d72 100644 struct list_head vbl_waiting; -@@ -691,15 +694,22 @@ struct drm_nouveau_private { +@@ -681,6 +685,9 @@ struct drm_nouveau_private { + /* For PFIFO and PGRAPH. */ + spinlock_t context_switch_lock; + ++ /* VM/PRAMIN flush, legacy PRAMIN aperture */ ++ spinlock_t vm_lock; ++ + /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ + struct nouveau_ramht *ramht; + struct nouveau_gpuobj *ramfc; +@@ -691,15 +698,22 @@ struct drm_nouveau_private { struct { enum { NOUVEAU_GART_NONE = 0, @@ -1043,7 +1146,7 @@ index 982d70b..e172d72 100644 } gart_info; /* nv10-nv40 tiling regions */ -@@ -740,14 +750,6 @@ struct drm_nouveau_private { +@@ -740,14 +754,6 @@ struct drm_nouveau_private { struct backlight_device *backlight; @@ -1058,7 +1161,7 @@ index 982d70b..e172d72 100644 struct { struct dentry *channel_root; } debugfs; -@@ -847,6 +849,7 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, +@@ -847,6 +853,7 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile, struct nouveau_fence *fence); extern const struct ttm_mem_type_manager_func nouveau_vram_manager; @@ -1066,7 +1169,7 @@ index 982d70b..e172d72 100644 /* nouveau_notifier.c */ extern int nouveau_notifier_init_channel(struct nouveau_channel *); -@@ -879,17 +882,17 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan, +@@ -879,17 +886,17 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan, extern void nouveau_channel_idle(struct nouveau_channel *chan); /* nouveau_object.c */ @@ -1088,7 +1191,7 @@ index 982d70b..e172d72 100644 extern int nouveau_gpuobj_early_init(struct drm_device *); extern int nouveau_gpuobj_init(struct drm_device *); -@@ -899,7 +902,7 @@ extern void nouveau_gpuobj_resume(struct drm_device *dev); +@@ -899,7 +906,7 @@ extern void nouveau_gpuobj_resume(struct drm_device *dev); extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, int (*exec)(struct nouveau_channel *, @@ -1097,7 +1200,7 @@ index 982d70b..e172d72 100644 extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, -@@ -1076,7 +1079,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); +@@ -1076,7 +1083,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); /* nv50_fb.c */ extern int nv50_fb_init(struct drm_device *); extern void nv50_fb_takedown(struct drm_device *); @@ -1106,7 +1209,7 @@ index 982d70b..e172d72 100644 /* nvc0_fb.c */ extern int nvc0_fb_init(struct drm_device *); -@@ -1189,7 +1192,7 @@ extern int nv50_graph_load_context(struct nouveau_channel *); +@@ -1189,7 +1196,7 @@ extern int nv50_graph_load_context(struct nouveau_channel *); extern int nv50_graph_unload_context(struct drm_device *); extern int nv50_grctx_init(struct nouveau_grctx *); extern void nv50_graph_tlb_flush(struct drm_device *dev); @@ -1115,7 +1218,7 @@ index 982d70b..e172d72 100644 extern struct nouveau_enum nv50_data_error_names[]; /* nvc0_graph.c */ -@@ -1295,7 +1298,7 @@ extern struct ttm_bo_driver nouveau_bo_driver; +@@ -1295,7 +1302,7 @@ extern struct ttm_bo_driver nouveau_bo_driver; extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, int size, int align, uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, @@ -1124,7 +1227,7 @@ index 982d70b..e172d72 100644 extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); extern int nouveau_bo_unpin(struct nouveau_bo *); extern int nouveau_bo_map(struct nouveau_bo *); -@@ -1356,9 +1359,9 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) +@@ -1356,9 +1363,9 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) /* nouveau_gem.c */ extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, @@ -1136,6 +1239,17 @@ index 982d70b..e172d72 100644 extern int nouveau_gem_object_new(struct drm_gem_object *); extern void nouveau_gem_object_del(struct drm_gem_object *); extern int nouveau_gem_ioctl_new(struct drm_device *, void *, +@@ -1398,8 +1405,8 @@ bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); + /* nv50_calc. */ + int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, + int *N1, int *M1, int *N2, int *M2, int *P); +-int nv50_calc_pll2(struct drm_device *, struct pll_lims *, +- int clk, int *N, int *fN, int *M, int *P); ++int nva3_calc_pll(struct drm_device *, struct pll_lims *, ++ int clk, int *N, int *fN, int *M, int *P); + + #ifndef ioread32_native + #ifdef __BIG_ENDIAN diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h index d432134..a3a88ad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fb.h @@ -1151,7 +1265,7 @@ index d432134..a3a88ad 100644 static inline struct nouveau_framebuffer * diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -index 60769d2..889c445 100644 +index 7826be0..39aee6d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -296,8 +296,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, @@ -1679,19 +1793,41 @@ index 4a8ad13..86c2e37 100644 static inline void cp_pos(struct nouveau_grctx *ctx, int offset) +diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c +index 053edf9..ba896e5 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_hw.c ++++ b/drivers/gpu/drm/nouveau/nouveau_hw.c +@@ -900,6 +900,7 @@ nv_save_state_ext(struct drm_device *dev, int head, + } + /* NV11 and NV20 don't have this, they stop at 0x52. */ + if (nv_gf4_disp_arch(dev)) { ++ rd_cio_state(dev, head, regp, NV_CIO_CRE_42); + rd_cio_state(dev, head, regp, NV_CIO_CRE_53); + rd_cio_state(dev, head, regp, NV_CIO_CRE_54); + +@@ -1003,6 +1004,7 @@ nv_load_state_ext(struct drm_device *dev, int head, + nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); + } + ++ wr_cio_state(dev, head, regp, NV_CIO_CRE_42); + wr_cio_state(dev, head, regp, NV_CIO_CRE_53); + wr_cio_state(dev, head, regp, NV_CIO_CRE_54); + diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index b0fb9bd..f017997 100644 +index b0fb9bd..4942294 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c -@@ -152,7 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev) +@@ -152,9 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - nouveau_bo_unpin(dev_priv->vga_ram); - nouveau_bo_ref(NULL, &dev_priv->vga_ram); - +- nouveau_bo_ref(NULL, &dev_priv->vga_ram); +- ttm_bo_device_release(&dev_priv->ttm.bdev); -@@ -393,11 +392,17 @@ nouveau_mem_vram_init(struct drm_device *dev) + + nouveau_ttm_global_release(dev_priv); +@@ -393,11 +390,17 @@ nouveau_mem_vram_init(struct drm_device *dev) struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; int ret, dma_bits; @@ -1714,7 +1850,7 @@ index b0fb9bd..f017997 100644 ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); if (ret) -@@ -419,14 +424,32 @@ nouveau_mem_vram_init(struct drm_device *dev) +@@ -419,14 +422,32 @@ nouveau_mem_vram_init(struct drm_device *dev) } /* reserve space at end of VRAM for PRAMIN */ @@ -1755,7 +1891,7 @@ index b0fb9bd..f017997 100644 ret = dev_priv->engine.vram.init(dev); if (ret) -@@ -455,13 +478,17 @@ nouveau_mem_vram_init(struct drm_device *dev) +@@ -455,13 +476,17 @@ nouveau_mem_vram_init(struct drm_device *dev) return ret; } @@ -1780,7 +1916,7 @@ index b0fb9bd..f017997 100644 } dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), -@@ -525,6 +552,7 @@ nouveau_mem_timing_init(struct drm_device *dev) +@@ -525,6 +550,7 @@ nouveau_mem_timing_init(struct drm_device *dev) u8 tRC; /* Byte 9 */ u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; @@ -1788,7 +1924,7 @@ index b0fb9bd..f017997 100644 u8 *mem = NULL, *entry; int i, recordlen, entries; -@@ -569,6 +597,12 @@ nouveau_mem_timing_init(struct drm_device *dev) +@@ -569,6 +595,12 @@ nouveau_mem_timing_init(struct drm_device *dev) if (!memtimings->timing) return; @@ -1801,7 +1937,7 @@ index b0fb9bd..f017997 100644 entry = mem + mem[1]; for (i = 0; i < entries; i++, entry += recordlen) { struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; -@@ -608,36 +642,67 @@ nouveau_mem_timing_init(struct drm_device *dev) +@@ -608,36 +640,67 @@ nouveau_mem_timing_init(struct drm_device *dev) /* XXX: I don't trust the -1's and +1's... they must come * from somewhere! */ @@ -1896,7 +2032,7 @@ index b0fb9bd..f017997 100644 } NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, -@@ -646,9 +711,10 @@ nouveau_mem_timing_init(struct drm_device *dev) +@@ -646,9 +709,10 @@ nouveau_mem_timing_init(struct drm_device *dev) NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", timing->reg_100230, timing->reg_100234, timing->reg_100238, timing->reg_10023c); @@ -1908,7 +2044,7 @@ index b0fb9bd..f017997 100644 memtimings->supported = true; } -@@ -666,13 +732,14 @@ nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size +@@ -666,13 +730,14 @@ nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); struct nouveau_mm *mm; @@ -1927,7 +2063,7 @@ index b0fb9bd..f017997 100644 if (ret) return ret; -@@ -700,9 +767,15 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, +@@ -700,9 +765,15 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, { struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); struct nouveau_vram_engine *vram = &dev_priv->engine.vram; @@ -1944,7 +2080,7 @@ index b0fb9bd..f017997 100644 } static int -@@ -715,7 +788,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, +@@ -715,7 +786,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); @@ -1953,7 +2089,7 @@ index b0fb9bd..f017997 100644 u32 size_nc = 0; int ret; -@@ -724,7 +797,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, +@@ -724,7 +795,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, mem->page_alignment << PAGE_SHIFT, size_nc, @@ -1962,7 +2098,7 @@ index b0fb9bd..f017997 100644 if (ret) { mem->mm_node = NULL; return (ret == -ENOSPC) ? 0 : ret; -@@ -771,3 +844,84 @@ const struct ttm_mem_type_manager_func nouveau_vram_manager = { +@@ -771,3 +842,84 @@ const struct ttm_mem_type_manager_func nouveau_vram_manager = { nouveau_vram_manager_del, nouveau_vram_manager_debug }; @@ -2069,18 +2205,28 @@ index 798eaf3..1f7483a 100644 #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c -index 5ea1676..7ba3fc0 100644 +index 5ea1676..5b39718 100644 --- a/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c -@@ -39,12 +39,11 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) +@@ -35,20 +35,22 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) + { + struct drm_device *dev = chan->dev; + struct nouveau_bo *ntfy = NULL; +- uint32_t flags; ++ uint32_t flags, ttmpl; int ret; - if (nouveau_vram_notify) +- if (nouveau_vram_notify) - flags = TTM_PL_FLAG_VRAM; -+ flags = NOUVEAU_GEM_DOMAIN_VRAM; - else +- else - flags = TTM_PL_FLAG_TT; ++ if (nouveau_vram_notify) { ++ flags = NOUVEAU_GEM_DOMAIN_VRAM; ++ ttmpl = TTM_PL_FLAG_VRAM; ++ } else { + flags = NOUVEAU_GEM_DOMAIN_GART; ++ ttmpl = TTM_PL_FLAG_TT; ++ } - ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, - 0, 0x0000, false, true, &ntfy); @@ -2088,7 +2234,12 @@ index 5ea1676..7ba3fc0 100644 if (ret) return ret; -@@ -100,6 +99,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, +- ret = nouveau_bo_pin(ntfy, flags); ++ ret = nouveau_bo_pin(ntfy, ttmpl); + if (ret) + goto out_err; + +@@ -100,6 +102,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, uint32_t *b_offset) { struct drm_device *dev = chan->dev; @@ -2096,7 +2247,7 @@ index 5ea1676..7ba3fc0 100644 struct nouveau_gpuobj *nobj = NULL; struct drm_mm_node *mem; uint32_t offset; -@@ -114,11 +114,16 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, +@@ -114,11 +117,16 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, return -ENOMEM; } @@ -2119,7 +2270,7 @@ index 5ea1676..7ba3fc0 100644 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c -index 30b6544..823800d 100644 +index 30b6544..59b446e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -36,6 +36,7 @@ @@ -2196,8 +2347,53 @@ index 30b6544..823800d 100644 } /* VRAM ctxdma */ +@@ -1013,19 +1039,20 @@ nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) + { + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_device *dev = gpuobj->dev; ++ unsigned long flags; + + if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { + u64 ptr = gpuobj->vinst + offset; + u32 base = ptr >> 16; + u32 val; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + if (dev_priv->ramin_base != base) { + dev_priv->ramin_base = base; + nv_wr32(dev, 0x001700, dev_priv->ramin_base); + } + val = nv_rd32(dev, 0x700000 + (ptr & 0xffff)); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + return val; + } + +@@ -1037,18 +1064,19 @@ nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) + { + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_device *dev = gpuobj->dev; ++ unsigned long flags; + + if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { + u64 ptr = gpuobj->vinst + offset; + u32 base = ptr >> 16; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + if (dev_priv->ramin_base != base) { + dev_priv->ramin_base = base; + nv_wr32(dev, 0x001700, dev_priv->ramin_base); + } + nv_wr32(dev, 0x700000 + (ptr & 0xffff), val); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + return; + } + diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c -index ac62a1b..670e3cb 100644 +index ac62a1b..3045566 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -134,7 +134,7 @@ nouveau_perf_init(struct drm_device *dev) @@ -2209,6 +2405,31 @@ index ac62a1b..670e3cb 100644 perflvl->core = ROM32(entry[1]) * 10; perflvl->memory = ROM32(entry[5]) * 20; break; +@@ -174,9 +174,21 @@ nouveau_perf_init(struct drm_device *dev) + #define subent(n) entry[perf[2] + ((n) * perf[3])] + perflvl->fanspeed = 0; /*XXX*/ + perflvl->voltage = entry[2]; +- perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000; +- perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000; +- perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000; ++ if (dev_priv->card_type == NV_50) { ++ perflvl->core = ROM16(subent(0)) & 0xfff; ++ perflvl->shader = ROM16(subent(1)) & 0xfff; ++ perflvl->memory = ROM16(subent(2)) & 0xfff; ++ } else { ++ perflvl->shader = ROM16(subent(3)) & 0xfff; ++ perflvl->core = perflvl->shader / 2; ++ perflvl->unk0a = ROM16(subent(4)) & 0xfff; ++ perflvl->memory = ROM16(subent(5)) & 0xfff; ++ } ++ ++ perflvl->core *= 1000; ++ perflvl->shader *= 1000; ++ perflvl->memory *= 1000; ++ perflvl->unk0a *= 1000; + break; + } + diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 4399e2f..0b1caeb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -2712,7 +2933,7 @@ index 9a250eb..2bf9686 100644 uint32_t diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index a54fc43..eb4f09e 100644 +index a54fc43..adf6dac 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -376,15 +376,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) @@ -2735,7 +2956,15 @@ index a54fc43..eb4f09e 100644 engine->fifo.channels = 128; engine->fifo.init = nv50_fifo_init; engine->fifo.takedown = nv50_fifo_takedown; -@@ -544,7 +540,6 @@ static int +@@ -513,6 +509,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) + engine->vram.get = nvc0_vram_new; + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nvc0_vram_flags_valid; ++ engine->pm.temp_get = nv84_temp_get; + break; + default: + NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); +@@ -544,7 +541,6 @@ static int nouveau_card_init_channel(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -2743,7 +2972,7 @@ index a54fc43..eb4f09e 100644 int ret; ret = nouveau_channel_alloc(dev, &dev_priv->channel, -@@ -552,41 +547,8 @@ nouveau_card_init_channel(struct drm_device *dev) +@@ -552,41 +548,8 @@ nouveau_card_init_channel(struct drm_device *dev) if (ret) return ret; @@ -2785,7 +3014,27 @@ index a54fc43..eb4f09e 100644 } static void nouveau_switcheroo_set_state(struct pci_dev *pdev, -@@ -904,7 +866,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) +@@ -646,6 +609,7 @@ nouveau_card_init(struct drm_device *dev) + spin_lock_init(&dev_priv->channels.lock); + spin_lock_init(&dev_priv->tile.lock); + spin_lock_init(&dev_priv->context_switch_lock); ++ spin_lock_init(&dev_priv->vm_lock); + + /* Make the CRTCs and I2C buses accessible */ + ret = engine->display.early_init(dev); +@@ -811,6 +775,11 @@ static void nouveau_card_takedown(struct drm_device *dev) + engine->mc.takedown(dev); + engine->display.late_takedown(dev); + ++ if (dev_priv->vga_ram) { ++ nouveau_bo_unpin(dev_priv->vga_ram); ++ nouveau_bo_ref(NULL, &dev_priv->vga_ram); ++ } ++ + mutex_lock(&dev->struct_mutex); + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); + ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); +@@ -904,7 +873,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) #ifdef CONFIG_X86 primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; #endif @@ -2794,7 +3043,7 @@ index a54fc43..eb4f09e 100644 remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary); return 0; } -@@ -929,12 +891,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) +@@ -929,12 +898,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", dev->pci_vendor, dev->pci_device, dev->pdev->class); @@ -2807,7 +3056,7 @@ index a54fc43..eb4f09e 100644 /* resource 0 is mmio regs */ /* resource 1 is linear FB */ /* resource 2 is RAMIN (mmio regs + 0x1000000) */ -@@ -947,7 +903,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) +@@ -947,7 +910,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) NV_ERROR(dev, "Unable to initialize the mmio mapping. " "Please report your setup to " DRIVER_EMAIL "\n"); ret = -EINVAL; @@ -2816,7 +3065,7 @@ index a54fc43..eb4f09e 100644 } NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", (unsigned long long)mmio_start_offs); -@@ -962,11 +918,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) +@@ -962,11 +925,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) /* Time to determine the card architecture */ reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); @@ -2830,7 +3079,7 @@ index a54fc43..eb4f09e 100644 /* NV04 or NV05 */ } else if ((reg0 & 0xff00fff0) == 0x20004000) { if (reg0 & 0x00f00000) -@@ -1054,8 +1012,6 @@ err_ramin: +@@ -1054,8 +1019,6 @@ err_ramin: iounmap(dev_priv->ramin); err_mmio: iounmap(dev_priv->mmio); @@ -2839,7 +3088,7 @@ index a54fc43..eb4f09e 100644 err_priv: kfree(dev_priv); dev->dev_private = NULL; -@@ -1126,7 +1082,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, +@@ -1126,7 +1089,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, getparam->value = 1; break; case NOUVEAU_GETPARAM_HAS_PAGEFLIP: @@ -3089,10 +3338,22 @@ index 04fdc00..75e87274 100644 default: NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c -index 297505e..5ffc5ba 100644 +index 297505e..9eaafcc 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c -@@ -790,8 +790,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, +@@ -376,7 +376,10 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) + */ + + /* framebuffer can be larger than crtc scanout area. */ +- regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); ++ regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = ++ XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); ++ regp->CRTC[NV_CIO_CRE_42] = ++ XLATE(fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11); + regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->crtc_hdisplay < 1280 ? + MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00; + regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) | +@@ -790,8 +793,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, if (atomic) { drm_fb = passed_fb; fb = nouveau_framebuffer(passed_fb); @@ -3102,7 +3363,37 @@ index 297505e..5ffc5ba 100644 /* If not atomic, we can go ahead and pin, and unpin the * old fb we were passed. */ -@@ -1031,7 +1030,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) +@@ -825,8 +827,11 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, + regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitch >> 3; + regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = + XLATE(drm_fb->pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); ++ regp->CRTC[NV_CIO_CRE_42] = ++ XLATE(drm_fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_RPC0_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CR_OFFSET_INDEX); ++ crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_42); + + /* Update the framebuffer location. */ + regp->fb_start = nv_crtc->fb.offset & ~3; +@@ -944,14 +949,14 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, + struct drm_gem_object *gem; + int ret = 0; + +- if (width != 64 || height != 64) +- return -EINVAL; +- + if (!buffer_handle) { + nv_crtc->cursor.hide(nv_crtc, true); + return 0; + } + ++ if (width != 64 || height != 64) ++ return -EINVAL; ++ + gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); + if (!gem) + return -ENOENT; +@@ -1031,7 +1036,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, @@ -3221,6 +3512,20 @@ index af75015..055677a 100644 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, +diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c +index b8e3edb..b8611b9 100644 +--- a/drivers/gpu/drm/nouveau/nv04_instmem.c ++++ b/drivers/gpu/drm/nouveau/nv04_instmem.c +@@ -95,6 +95,9 @@ nv04_instmem_takedown(struct drm_device *dev) + nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); + nouveau_gpuobj_ref(NULL, &dev_priv->ramro); + nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); ++ ++ if (drm_mm_initialized(&dev_priv->ramin_heap)) ++ drm_mm_takedown(&dev_priv->ramin_heap); + } + + int diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index 8c92edb..531d7ba 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c @@ -3312,8 +3617,103 @@ index f3d9c05..f0ac2a7 100644 switch (dev_priv->chipset) { case 0x40: +diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c +index de81151..8cf63a8 100644 +--- a/drivers/gpu/drm/nouveau/nv50_calc.c ++++ b/drivers/gpu/drm/nouveau/nv50_calc.c +@@ -23,7 +23,6 @@ + */ + + #include "drmP.h" +-#include "drm_fixed.h" + #include "nouveau_drv.h" + #include "nouveau_hw.h" + +@@ -47,45 +46,52 @@ nv50_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, + } + + int +-nv50_calc_pll2(struct drm_device *dev, struct pll_lims *pll, int clk, +- int *N, int *fN, int *M, int *P) ++nva3_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, ++ int *pN, int *pfN, int *pM, int *P) + { +- fixed20_12 fb_div, a, b; +- u32 refclk = pll->refclk / 10; +- u32 max_vco_freq = pll->vco1.maxfreq / 10; +- u32 max_vco_inputfreq = pll->vco1.max_inputfreq / 10; +- clk /= 10; ++ u32 best_err = ~0, err; ++ int M, lM, hM, N, fN; + +- *P = max_vco_freq / clk; ++ *P = pll->vco1.maxfreq / clk; + if (*P > pll->max_p) + *P = pll->max_p; + if (*P < pll->min_p) + *P = pll->min_p; + +- /* *M = floor((refclk + max_vco_inputfreq) / max_vco_inputfreq); */ +- a.full = dfixed_const(refclk + max_vco_inputfreq); +- b.full = dfixed_const(max_vco_inputfreq); +- a.full = dfixed_div(a, b); +- a.full = dfixed_floor(a); +- *M = dfixed_trunc(a); ++ lM = (pll->refclk + pll->vco1.max_inputfreq) / pll->vco1.max_inputfreq; ++ lM = max(lM, (int)pll->vco1.min_m); ++ hM = (pll->refclk + pll->vco1.min_inputfreq) / pll->vco1.min_inputfreq; ++ hM = min(hM, (int)pll->vco1.max_m); + +- /* fb_div = (vco * *M) / refclk; */ +- fb_div.full = dfixed_const(clk * *P); +- fb_div.full = dfixed_mul(fb_div, a); +- a.full = dfixed_const(refclk); +- fb_div.full = dfixed_div(fb_div, a); ++ for (M = lM; M <= hM; M++) { ++ u32 tmp = clk * *P * M; ++ N = tmp / pll->refclk; ++ fN = tmp % pll->refclk; ++ if (!pfN && fN >= pll->refclk / 2) ++ N++; + +- /* *N = floor(fb_div); */ +- a.full = dfixed_floor(fb_div); +- *N = dfixed_trunc(fb_div); ++ if (N < pll->vco1.min_n) ++ continue; ++ if (N > pll->vco1.max_n) ++ break; + +- /* *fN = (fmod(fb_div, 1.0) * 8192) - 4096; */ +- b.full = dfixed_const(8192); +- a.full = dfixed_mul(a, b); +- fb_div.full = dfixed_mul(fb_div, b); +- fb_div.full = fb_div.full - a.full; +- *fN = dfixed_trunc(fb_div) - 4096; +- *fN &= 0xffff; ++ err = abs(clk - (pll->refclk * N / M / *P)); ++ if (err < best_err) { ++ best_err = err; ++ *pN = N; ++ *pM = M; ++ } + +- return clk; ++ if (pfN) { ++ *pfN = (((fN << 13) / pll->refclk) - 4096) & 0xffff; ++ return clk; ++ } ++ } ++ ++ if (unlikely(best_err == ~0)) { ++ NV_ERROR(dev, "unable to find matching pll values\n"); ++ return -EINVAL; ++ } ++ ++ return pll->refclk * *pN / *pM / *P; + } diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c -index 9023c4d..e900a51 100644 +index 9023c4d..ebabacf 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -65,7 +65,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) @@ -3345,6 +3745,42 @@ index 9023c4d..e900a51 100644 struct drm_display_mode *native_mode = NULL; struct drm_display_mode *mode = &nv_crtc->base.mode; uint32_t outX, outY, horiz, vert; +@@ -288,7 +286,7 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) + nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); + } else + if (dev_priv->chipset < NV_C0) { +- ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); ++ ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); + if (ret <= 0) + return 0; + +@@ -300,7 +298,7 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) + nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); + nv_wr32(dev, pll.reg + 8, N2); + } else { +- ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); ++ ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); + if (ret <= 0) + return 0; + +@@ -351,14 +349,14 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, + struct drm_gem_object *gem; + int ret = 0, i; + +- if (width != 64 || height != 64) +- return -EINVAL; +- + if (!buffer_handle) { + nv_crtc->cursor.hide(nv_crtc, true); + return 0; + } + ++ if (width != 64 || height != 64) ++ return -EINVAL; ++ + gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); + if (!gem) + return -ENOENT; @@ -445,6 +443,39 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) { } @@ -3674,7 +4110,7 @@ index 875414b..808f3ec 100644 uint32_t mode_ctl = 0, mode_ctl2 = 0; int ret; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c -index 7cc94ed..75a376c 100644 +index 7cc94ed..74a3f68 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -24,6 +24,7 @@ @@ -3909,7 +4345,36 @@ index 7cc94ed..75a376c 100644 } static u16 -@@ -466,11 +600,12 @@ static void +@@ -383,13 +517,25 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, + if (bios->fp.if_is_24bit) + script |= 0x0200; + } else { ++ /* determine number of lvds links */ ++ if (nv_connector && nv_connector->edid && ++ nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { ++ /* http://www.spwg.org */ ++ if (((u8 *)nv_connector->edid)[121] == 2) ++ script |= 0x0100; ++ } else + if (pxclk >= bios->fp.duallink_transition_clk) { + script |= 0x0100; ++ } ++ ++ /* determine panel depth */ ++ if (script & 0x0100) { + if (bios->fp.strapless_is_24bit & 2) + script |= 0x0200; +- } else +- if (bios->fp.strapless_is_24bit & 1) +- script |= 0x0200; ++ } else { ++ if (bios->fp.strapless_is_24bit & 1) ++ script |= 0x0200; ++ } + + if (nv_connector && nv_connector->edid && + (nv_connector->edid->revision >= 4) && +@@ -466,11 +612,12 @@ static void nv50_display_unk10_handler(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -3923,7 +4388,7 @@ index 7cc94ed..75a376c 100644 nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); -@@ -541,7 +676,7 @@ nv50_display_unk10_handler(struct drm_device *dev) +@@ -541,7 +688,7 @@ nv50_display_unk10_handler(struct drm_device *dev) if (dcb->type == type && (dcb->or & (1 << or))) { nouveau_bios_run_display_table(dev, dcb, 0, -1); @@ -3932,7 +4397,7 @@ index 7cc94ed..75a376c 100644 goto ack; } } -@@ -587,15 +722,16 @@ static void +@@ -587,15 +734,16 @@ static void nv50_display_unk20_handler(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -3952,7 +4417,7 @@ index 7cc94ed..75a376c 100644 } /* CRTC clock change requested? */ -@@ -692,9 +828,9 @@ nv50_display_unk20_handler(struct drm_device *dev) +@@ -692,9 +840,9 @@ nv50_display_unk20_handler(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); } @@ -3965,7 +4430,7 @@ index 7cc94ed..75a376c 100644 ack: nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); -@@ -735,13 +871,13 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) +@@ -735,13 +883,13 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) static void nv50_display_unk40_handler(struct drm_device *dev) { @@ -3984,7 +4449,7 @@ index 7cc94ed..75a376c 100644 if (!dcb) goto ack; -@@ -754,12 +890,10 @@ ack: +@@ -754,12 +902,10 @@ ack: nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); } @@ -4000,7 +4465,7 @@ index 7cc94ed..75a376c 100644 for (;;) { uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); -@@ -807,7 +941,7 @@ nv50_display_error_handler(struct drm_device *dev) +@@ -807,7 +953,7 @@ nv50_display_error_handler(struct drm_device *dev) static void nv50_display_isr(struct drm_device *dev) { @@ -4009,7 +4474,7 @@ index 7cc94ed..75a376c 100644 uint32_t delayed = 0; while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { -@@ -835,8 +969,7 @@ nv50_display_isr(struct drm_device *dev) +@@ -835,8 +981,7 @@ nv50_display_isr(struct drm_device *dev) NV50_PDISPLAY_INTR_1_CLK_UNK40)); if (clock) { nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); @@ -5154,7 +5619,7 @@ index 336aab2..de9abff 100644 else xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c -index e57caa2..fa94973 100644 +index e57caa2..993ad3f 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -300,7 +300,7 @@ nv50_instmem_resume(struct drm_device *dev) @@ -5166,6 +5631,36 @@ index e57caa2..fa94973 100644 struct nouveau_vma chan_vma; u32 align; }; +@@ -404,23 +404,25 @@ void + nv50_instmem_flush(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ unsigned long flags; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x00330c, 0x00000001); + if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) + NV_ERROR(dev, "PRAMIN flush timeout\n"); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } + + void + nv84_instmem_flush(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ unsigned long flags; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x070000, 0x00000001); + if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) + NV_ERROR(dev, "PRAMIN flush timeout\n"); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } + diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index b4a5ecb..c25c593 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c @@ -5191,7 +5686,7 @@ index b4a5ecb..c25c593 100644 struct drm_device *dev = encoder->dev; struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c -index 6144156..4fd3432 100644 +index 6144156..6c26944 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c @@ -31,7 +31,6 @@ void @@ -5257,6 +5752,20 @@ index 6144156..4fd3432 100644 nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; +@@ -170,10 +174,11 @@ void + nv50_vm_flush_engine(struct drm_device *dev, int engine) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ unsigned long flags; + +- spin_lock(&dev_priv->ramin_lock); ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + nv_wr32(dev, 0x100c80, (engine << 16) | 1); + if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) + NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); +- spin_unlock(&dev_priv->ramin_lock); ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c index 58e98ad..ffbc3d8 100644 --- a/drivers/gpu/drm/nouveau/nv50_vram.c @@ -5391,6 +5900,312 @@ index ec18ae1..fabc7fd 100644 - nv50_fb_vm_trap(dev, show, "PCRYPT"); + nv50_fb_vm_trap(dev, show); } +diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c +index dbbafed..e4b2b9e 100644 +--- a/drivers/gpu/drm/nouveau/nva3_pm.c ++++ b/drivers/gpu/drm/nouveau/nva3_pm.c +@@ -27,32 +27,74 @@ + #include "nouveau_bios.h" + #include "nouveau_pm.h" + +-/*XXX: boards using limits 0x40 need fixing, the register layout +- * is correct here, but, there's some other funny magic +- * that modifies things, so it's not likely we'll set/read +- * the correct timings yet.. working on it... ++/* This is actually a lot more complex than it appears here, but hopefully ++ * this should be able to deal with what the VBIOS leaves for us.. ++ * ++ * If not, well, I'll jump off that bridge when I come to it. + */ + + struct nva3_pm_state { +- struct pll_lims pll; +- int N, M, P; ++ enum pll_types type; ++ u32 src0; ++ u32 src1; ++ u32 ctrl; ++ u32 coef; ++ u32 old_pnm; ++ u32 new_pnm; ++ u32 new_div; + }; + ++static int ++nva3_pm_pll_offset(u32 id) ++{ ++ static const u32 pll_map[] = { ++ 0x00, PLL_CORE, ++ 0x01, PLL_SHADER, ++ 0x02, PLL_MEMORY, ++ 0x00, 0x00 ++ }; ++ const u32 *map = pll_map; ++ ++ while (map[1]) { ++ if (id == map[1]) ++ return map[0]; ++ map += 2; ++ } ++ ++ return -ENOENT; ++} ++ + int + nva3_pm_clock_get(struct drm_device *dev, u32 id) + { ++ u32 src0, src1, ctrl, coef; + struct pll_lims pll; +- int P, N, M, ret; +- u32 reg; ++ int ret, off; ++ int P, N, M; + + ret = get_pll_limits(dev, id, &pll); + if (ret) + return ret; + +- reg = nv_rd32(dev, pll.reg + 4); +- P = (reg & 0x003f0000) >> 16; +- N = (reg & 0x0000ff00) >> 8; +- M = (reg & 0x000000ff); ++ off = nva3_pm_pll_offset(id); ++ if (off < 0) ++ return off; ++ ++ src0 = nv_rd32(dev, 0x4120 + (off * 4)); ++ src1 = nv_rd32(dev, 0x4160 + (off * 4)); ++ ctrl = nv_rd32(dev, pll.reg + 0); ++ coef = nv_rd32(dev, pll.reg + 4); ++ NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ id, src0, src1, ctrl, coef); ++ ++ if (ctrl & 0x00000008) { ++ u32 div = ((src1 & 0x003c0000) >> 18) + 1; ++ return (pll.refclk * 2) / div; ++ } ++ ++ P = (coef & 0x003f0000) >> 16; ++ N = (coef & 0x0000ff00) >> 8; ++ M = (coef & 0x000000ff); + return pll.refclk * N / M / P; + } + +@@ -60,36 +102,103 @@ void * + nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, + u32 id, int khz) + { +- struct nva3_pm_state *state; +- int dummy, ret; ++ struct nva3_pm_state *pll; ++ struct pll_lims limits; ++ int N, M, P, diff; ++ int ret, off; ++ ++ ret = get_pll_limits(dev, id, &limits); ++ if (ret < 0) ++ return (ret == -ENOENT) ? NULL : ERR_PTR(ret); ++ ++ off = nva3_pm_pll_offset(id); ++ if (id < 0) ++ return ERR_PTR(-EINVAL); + +- state = kzalloc(sizeof(*state), GFP_KERNEL); +- if (!state) ++ ++ pll = kzalloc(sizeof(*pll), GFP_KERNEL); ++ if (!pll) + return ERR_PTR(-ENOMEM); ++ pll->type = id; ++ pll->src0 = 0x004120 + (off * 4); ++ pll->src1 = 0x004160 + (off * 4); ++ pll->ctrl = limits.reg + 0; ++ pll->coef = limits.reg + 4; + +- ret = get_pll_limits(dev, id, &state->pll); +- if (ret < 0) { +- kfree(state); +- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); ++ /* If target clock is within [-2, 3) MHz of a divisor, we'll ++ * use that instead of calculating MNP values ++ */ ++ pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16); ++ if (pll->new_div) { ++ diff = khz - ((limits.refclk * 2) / pll->new_div); ++ if (diff < -2000 || diff >= 3000) ++ pll->new_div = 0; + } + +- ret = nv50_calc_pll2(dev, &state->pll, khz, &state->N, &dummy, +- &state->M, &state->P); +- if (ret < 0) { +- kfree(state); +- return ERR_PTR(ret); ++ if (!pll->new_div) { ++ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ ++ pll->new_pnm = (P << 16) | (N << 8) | M; ++ pll->new_div = 2 - 1; ++ } else { ++ pll->new_pnm = 0; ++ pll->new_div--; + } + +- return state; ++ if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101) ++ pll->old_pnm = nv_rd32(dev, pll->coef); ++ return pll; + } + + void + nva3_pm_clock_set(struct drm_device *dev, void *pre_state) + { +- struct nva3_pm_state *state = pre_state; +- u32 reg = state->pll.reg; ++ struct nva3_pm_state *pll = pre_state; ++ u32 ctrl = 0; ++ ++ /* For the memory clock, NVIDIA will build a "script" describing ++ * the reclocking process and ask PDAEMON to execute it. ++ */ ++ if (pll->type == PLL_MEMORY) { ++ nv_wr32(dev, 0x100210, 0); ++ nv_wr32(dev, 0x1002dc, 1); ++ nv_wr32(dev, 0x004018, 0x00001000); ++ ctrl = 0x18000100; ++ } ++ ++ if (pll->old_pnm || !pll->new_pnm) { ++ nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 | ++ (pll->new_div << 18)); ++ nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); ++ nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); ++ } ++ ++ if (pll->new_pnm) { ++ nv_mask(dev, pll->src0, 0x00000101, 0x00000101); ++ nv_wr32(dev, pll->coef, pll->new_pnm); ++ nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); ++ nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000); ++ nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010); ++ nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl); ++ nv_mask(dev, pll->src1, 0x00000100, 0x00000000); ++ nv_mask(dev, pll->src1, 0x00000001, 0x00000000); ++ if (pll->type == PLL_MEMORY) ++ nv_wr32(dev, 0x4018, 0x10005000); ++ } else { ++ nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); ++ nv_mask(dev, pll->src0, 0x00000100, 0x00000000); ++ nv_mask(dev, pll->src0, 0x00000001, 0x00000000); ++ if (pll->type == PLL_MEMORY) ++ nv_wr32(dev, 0x4018, 0x1000d000); ++ } ++ ++ if (pll->type == PLL_MEMORY) { ++ nv_wr32(dev, 0x1002dc, 0); ++ nv_wr32(dev, 0x100210, 0x80000000); ++ } + +- nv_wr32(dev, reg + 4, (state->P << 16) | (state->N << 8) | state->M); +- kfree(state); ++ kfree(pll); + } + +diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c +index 26a9960..08e6b11 100644 +--- a/drivers/gpu/drm/nouveau/nvc0_fb.c ++++ b/drivers/gpu/drm/nouveau/nvc0_fb.c +@@ -1,5 +1,5 @@ + /* +- * Copyright 2010 Red Hat Inc. ++ * Copyright 2011 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), +@@ -23,16 +23,80 @@ + */ + + #include "drmP.h" +- ++#include "drm.h" + #include "nouveau_drv.h" ++#include "nouveau_drm.h" ++ ++struct nvc0_fb_priv { ++ struct page *r100c10_page; ++ dma_addr_t r100c10; ++}; ++ ++static void ++nvc0_fb_destroy(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ struct nvc0_fb_priv *priv = pfb->priv; ++ ++ if (priv->r100c10_page) { ++ pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, ++ PCI_DMA_BIDIRECTIONAL); ++ __free_page(priv->r100c10_page); ++ } ++ ++ kfree(priv); ++ pfb->priv = NULL; ++} ++ ++static int ++nvc0_fb_create(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; ++ struct nvc0_fb_priv *priv; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ pfb->priv = priv; ++ ++ priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); ++ if (!priv->r100c10_page) { ++ nvc0_fb_destroy(dev); ++ return -ENOMEM; ++ } ++ ++ priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, ++ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { ++ nvc0_fb_destroy(dev); ++ return -EFAULT; ++ } ++ ++ return 0; ++} + + int + nvc0_fb_init(struct drm_device *dev) + { ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nvc0_fb_priv *priv; ++ int ret; ++ ++ if (!dev_priv->engine.fb.priv) { ++ ret = nvc0_fb_create(dev); ++ if (ret) ++ return ret; ++ } ++ priv = dev_priv->engine.fb.priv; ++ ++ nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); + return 0; + } + + void + nvc0_fb_takedown(struct drm_device *dev) + { ++ nvc0_fb_destroy(dev); + } diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c index e6f92c5..55a4245 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fifo.c @@ -5777,7 +6592,7 @@ index f880ff7..6cede9f 100644 gpc = (gpc + 1) % priv->gpc_nr; } while (!tpnr[gpc]); diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c -index e4e83c2..69af0ba 100644 +index e4e83c2..a179e6c 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vm.c +++ b/drivers/gpu/drm/nouveau/nvc0_vm.c @@ -59,7 +59,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) @@ -5803,6 +6618,43 @@ index e4e83c2..69af0ba 100644 nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys)); pte += 8; +@@ -104,20 +104,27 @@ nvc0_vm_flush(struct nouveau_vm *vm) + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct drm_device *dev = vm->dev; + struct nouveau_vm_pgd *vpgd; +- u32 r100c80, engine; ++ unsigned long flags; ++ u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; + + pinstmem->flush(vm->dev); + +- if (vm == dev_priv->chan_vm) +- engine = 1; +- else +- engine = 5; +- ++ spin_lock_irqsave(&dev_priv->vm_lock, flags); + list_for_each_entry(vpgd, &vm->pgd_list, head) { +- r100c80 = nv_rd32(dev, 0x100c80); ++ /* looks like maybe a "free flush slots" counter, the ++ * faster you write to 0x100cbc to more it decreases ++ */ ++ if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { ++ NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", ++ nv_rd32(dev, 0x100c80), engine); ++ } + nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); + nv_wr32(dev, 0x100cbc, 0x80000000 | engine); +- if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80)) +- NV_ERROR(dev, "vm flush timeout eng %d\n", engine); ++ /* wait for flush to be queued? */ ++ if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { ++ NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", ++ nv_rd32(dev, 0x100c80), engine); ++ } + } ++ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); + } diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c index 858eda5..67c6ec6 100644 --- a/drivers/gpu/drm/nouveau/nvc0_vram.c @@ -5910,3 +6762,16 @@ index 858eda5..67c6ec6 100644 return 0; } +diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/nvreg.h +index fe0f253..bbfb1a6 100644 +--- a/drivers/gpu/drm/nouveau/nvreg.h ++++ b/drivers/gpu/drm/nouveau/nvreg.h +@@ -277,6 +277,8 @@ + # define NV_CIO_CRE_EBR_VDE_11 2:2 + # define NV_CIO_CRE_EBR_VRS_11 4:4 + # define NV_CIO_CRE_EBR_VBS_11 6:6 ++# define NV_CIO_CRE_42 0x42 ++# define NV_CIO_CRE_42_OFFSET_11 6:6 + # define NV_CIO_CRE_43 0x43 + # define NV_CIO_CRE_44 0x44 /* head control */ + # define NV_CIO_CRE_CSB 0x45 /* colour saturation boost */ diff --git a/kernel.spec b/kernel.spec index 587ce74f5..4ef6550cb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 29 +%global baserelease 30 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2017,6 +2017,12 @@ fi # and build. %changelog +* Fri May 27 2011 Ben Skeggs 2.6.38.7-30 +- nouveau: minor fixes for various issues from upstream +- nv40 modesetting fix (rhbz#708235) +- nv50+ support for LVDS panels using SPWG spec (blank/corrupt screen fixes) +- nva3+ pm clock get/set fixes + * Wed May 25 2011 Dave Airlie - drm-radeon-update2.patch: more radeon updates + cayman accel support From 5e40603dafd7ef6c68a733e56ae2ca367da3c9ae Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 27 May 2011 15:02:33 +1000 Subject: [PATCH 66/99] nouveau: fix patch --- drm-nouveau-updates.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index d0a6bfe53..7a703e897 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -3513,7 +3513,7 @@ index af75015..055677a 100644 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c -index b8e3edb..b8611b9 100644 +index b8e3edb..0671b7f 100644 --- a/drivers/gpu/drm/nouveau/nv04_instmem.c +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c @@ -95,6 +95,9 @@ nv04_instmem_takedown(struct drm_device *dev) @@ -3521,7 +3521,7 @@ index b8e3edb..b8611b9 100644 nouveau_gpuobj_ref(NULL, &dev_priv->ramro); nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); + -+ if (drm_mm_initialized(&dev_priv->ramin_heap)) ++ if (dev_priv->ramin_heap.free_stack.next) + drm_mm_takedown(&dev_priv->ramin_heap); } From de4207af711d4873db6bf774e3527a8684ad81e6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 29 May 2011 16:43:12 -0400 Subject: [PATCH 67/99] fix oops on pageflipping sometimes (#680651) --- drm-radeon-pageflip-oops-fix.patch | 69 ++++++++++++++++++++++++++++++ kernel.spec | 5 +++ 2 files changed, 74 insertions(+) create mode 100644 drm-radeon-pageflip-oops-fix.patch diff --git a/drm-radeon-pageflip-oops-fix.patch b/drm-radeon-pageflip-oops-fix.patch new file mode 100644 index 000000000..785b61284 --- /dev/null +++ b/drm-radeon-pageflip-oops-fix.patch @@ -0,0 +1,69 @@ +From ee11d4db3389aab9df38edb3eed4d5822320d5f1 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Sun, 29 May 2011 17:48:32 +1000 +Subject: [PATCH] drm/radeon: fix oops in ttm reserve when pageflipping (v2) + +We need to take a reference to this object, pinning doesn't take a reference +so if userspace deletes the object it can disappear even if pinned. + +v2: fix error paths to unreference properly also. + +should fix: +https://bugzilla.kernel.org/show_bug.cgi?id=32402 +and +https://bugzilla.redhat.com/show_bug.cgi?id=680651 + +Signed-off-by: Dave Airlie +--- + drivers/gpu/drm/radeon/radeon_display.c | 13 ++++++++----- + 1 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c +index ae247ee..292f73f 100644 +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -264,6 +264,8 @@ static void radeon_unpin_work_func(struct work_struct *__work) + radeon_bo_unreserve(work->old_rbo); + } else + DRM_ERROR("failed to reserve buffer after flip\n"); ++ ++ drm_gem_object_unreference_unlocked(work->old_rbo->gobj); + kfree(work); + } + +@@ -371,6 +373,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, + new_radeon_fb = to_radeon_framebuffer(fb); + /* schedule unpin of the old buffer */ + obj = old_radeon_fb->obj; ++ /* take a reference to the old object */ ++ drm_gem_object_reference(obj); + rbo = obj->driver_private; + work->old_rbo = rbo; + INIT_WORK(&work->work, radeon_unpin_work_func); +@@ -378,12 +382,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, + /* We borrow the event spin lock for protecting unpin_work */ + spin_lock_irqsave(&dev->event_lock, flags); + if (radeon_crtc->unpin_work) { +- spin_unlock_irqrestore(&dev->event_lock, flags); +- kfree(work); +- radeon_fence_unref(&fence); +- + DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); +- return -EBUSY; ++ r = -EBUSY; ++ goto unlock_free; + } + radeon_crtc->unpin_work = work; + radeon_crtc->deferred_flip_completion = 0; +@@ -497,6 +498,8 @@ pflip_cleanup1: + pflip_cleanup: + spin_lock_irqsave(&dev->event_lock, flags); + radeon_crtc->unpin_work = NULL; ++unlock_free: ++ drm_gem_object_unreference_unlocked(old_radeon_fb->obj); + spin_unlock_irqrestore(&dev->event_lock, flags); + radeon_fence_unref(&fence); + kfree(work); +-- +1.7.4.4 + diff --git a/kernel.spec b/kernel.spec index 4ef6550cb..43c23524c 100644 --- a/kernel.spec +++ b/kernel.spec @@ -688,6 +688,7 @@ Patch1829: drm-intel-restore-mode.patch Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch Patch1840: drm-radeon-update.patch Patch1841: drm-radeon-update2.patch +Patch1842: drm-radeon-pageflip-oops-fix.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1346,6 +1347,7 @@ ApplyPatch drm-intel-restore-mode.patch ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -R ApplyPatch drm-radeon-update.patch ApplyPatch drm-radeon-update2.patch +ApplyPatch drm-radeon-pageflip-oops-fix.patch # linux1394 git patches #ApplyPatch linux-2.6-firewire-git-update.patch @@ -2017,6 +2019,9 @@ fi # and build. %changelog +* Sun May 29 2011 Dave Airlie +- fix oops on pageflipping sometimes (#680651) + * Fri May 27 2011 Ben Skeggs 2.6.38.7-30 - nouveau: minor fixes for various issues from upstream - nv40 modesetting fix (rhbz#708235) From 53392f03f52c2a02804c739c35694bb1635ceb36 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 31 May 2011 12:57:52 -0400 Subject: [PATCH 68/99] Delete unused intel drm patches --- drm-intel-big-hammer.patch | 21 ----- drm-intel-edp-fixes.patch | 44 ---------- drm-intel-eeebox-eb1007-quirk.patch | 36 -------- drm-intel-make-lvds-work.patch | 23 ----- drm-intel-next.patch | 1 - drm-intel-restore-mode.patch | 128 ---------------------------- 6 files changed, 253 deletions(-) delete mode 100644 drm-intel-big-hammer.patch delete mode 100644 drm-intel-edp-fixes.patch delete mode 100644 drm-intel-eeebox-eb1007-quirk.patch delete mode 100644 drm-intel-make-lvds-work.patch delete mode 100644 drm-intel-next.patch delete mode 100644 drm-intel-restore-mode.patch diff --git a/drm-intel-big-hammer.patch b/drm-intel-big-hammer.patch deleted file mode 100644 index bf152af3b..000000000 --- a/drm-intel-big-hammer.patch +++ /dev/null @@ -1,21 +0,0 @@ -omgwtfbbqchainsaw? ---- - drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) - -diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -index e698343..21e601d1 100644 ---- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c -+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c -@@ -1090,6 +1090,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, - if (ret) - goto pre_mutex_err; - -+ /* We don't get the flushing right for these chipsets, use the -+ * big hammer for now to avoid random crashiness. */ -+ if (IS_I85X(dev) || IS_I865G(dev)) -+ wbinvd(); -+ - if (dev_priv->mm.suspended) { - mutex_unlock(&dev->struct_mutex); - ret = -EBUSY; diff --git a/drm-intel-edp-fixes.patch b/drm-intel-edp-fixes.patch deleted file mode 100644 index c77ef116c..000000000 --- a/drm-intel-edp-fixes.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c -index f737960..b1f8164 100644 ---- a/drivers/gpu/drm/i915/i915_drv.c -+++ b/drivers/gpu/drm/i915/i915_drv.c -@@ -509,6 +509,8 @@ i915_pci_remove(struct pci_dev *pdev) - { - struct drm_device *dev = pci_get_drvdata(pdev); - -+ pci_disable_device(pdev); /* core did previous enable */ -+ - drm_put_dev(dev); - } - -diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c -index 300f64b..2e3db37 100644 ---- a/drivers/gpu/drm/i915/intel_dp.c -+++ b/drivers/gpu/drm/i915/intel_dp.c -@@ -795,7 +795,8 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) - { - struct drm_device *dev = intel_dp->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; -- u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; -+ u32 pp, idle_on = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; -+ u32 idle_on_mask = PP_ON | PP_SEQUENCE_STATE_MASK; - - if (I915_READ(PCH_PP_STATUS) & PP_ON) - return true; -@@ -816,7 +817,7 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) - */ - msleep(300); - -- if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask, -+ if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on, - 5000)) - DRM_ERROR("panel on wait timed out: 0x%08x\n", - I915_READ(PCH_PP_STATUS)); -@@ -922,6 +923,7 @@ static void intel_dp_prepare(struct drm_encoder *encoder) - - if (is_edp(intel_dp)) { - ironlake_edp_backlight_off(dev); -+ ironlake_edp_panel_off(dev); - ironlake_edp_panel_on(intel_dp); - if (!is_pch_edp(intel_dp)) - ironlake_edp_pll_on(encoder); diff --git a/drm-intel-eeebox-eb1007-quirk.patch b/drm-intel-eeebox-eb1007-quirk.patch deleted file mode 100644 index 9ae3604e7..000000000 --- a/drm-intel-eeebox-eb1007-quirk.patch +++ /dev/null @@ -1,36 +0,0 @@ -From ab737b006568d01204cc51368c7e2067eecb2cff Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 7 Apr 2011 13:31:57 +0200 -Subject: [PATCH] drm/i915: Add a no lvds quirk for the Asus EeeBox PC EB1007 - -I found this while figuring out why gnome-shell would not run on my -Asus EeeBox PC EB1007. As a standalone "pc" this device cleary does not have -an internal panel, yet it claims it does. Add a quirk to fix this. - -Signed-off-by: Hans de Goede ---- - drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ - 1 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c -index a562bd2..954822a 100644 ---- a/drivers/gpu/drm/i915/intel_lvds.c -+++ b/drivers/gpu/drm/i915/intel_lvds.c -@@ -724,6 +724,14 @@ static const struct dmi_system_id intel_no_lvds[] = { - DMI_MATCH(DMI_PRODUCT_NAME, "U800"), - }, - }, -+ { -+ .callback = intel_no_lvds_dmi_callback, -+ .ident = "Asus EeeBox PC EB1007", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), -+ }, -+ }, - - { } /* terminating entry */ - }; --- -1.7.4.2 - diff --git a/drm-intel-make-lvds-work.patch b/drm-intel-make-lvds-work.patch deleted file mode 100644 index 209deb295..000000000 --- a/drm-intel-make-lvds-work.patch +++ /dev/null @@ -1,23 +0,0 @@ - drivers/gpu/drm/i915/intel_display.c | 2 -- - 1 files changed, 0 insertions(+), 2 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c -index 990f065..171a797 100644 ---- a/drivers/gpu/drm/i915/intel_display.c -+++ b/drivers/gpu/drm/i915/intel_display.c -@@ -4568,7 +4568,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - struct drm_connector *connector, int dpms_mode) - { - struct drm_encoder *encoder = &intel_encoder->base; -- struct drm_device *dev = encoder->dev; - struct drm_crtc *crtc = encoder->crtc; - struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -@@ -4578,7 +4577,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, - connector->encoder = NULL; - intel_encoder->load_detect_temp = false; - crtc->enabled = drm_helper_crtc_in_use(crtc); -- drm_helper_disable_unused_functions(dev); - } - - /* Switch crtc and encoder back off if necessary */ diff --git a/drm-intel-next.patch b/drm-intel-next.patch deleted file mode 100644 index c6cac6926..000000000 --- a/drm-intel-next.patch +++ /dev/null @@ -1 +0,0 @@ -empty diff --git a/drm-intel-restore-mode.patch b/drm-intel-restore-mode.patch deleted file mode 100644 index b394ca00d..000000000 --- a/drm-intel-restore-mode.patch +++ /dev/null @@ -1,128 +0,0 @@ -From e8e7a2b8ccfdae0d4cb6bd25824bbedcd42da316 Mon Sep 17 00:00:00 2001 -From: Dave Airlie -Date: Thu, 21 Apr 2011 22:18:32 +0100 -Subject: [PATCH] drm/i915: restore only the mode of this driver on lastclose (v2) - -i915 calls the panic handler function on last close to reset the modes, -however this is a really bad idea for multi-gpu machines, esp shareable -gpus machines. So add a new entry point for the driver to just restore -its own fbcon mode. - -v2: move code into fb helper, fix panic code to block mode change on -powered off GPUs. - -[airlied: this hits drm core and I wrote it and it was reviewed on intel-gfx - so really I signed it off twice ;-).] -Signed-off-by: Chris Wilson -Signed-off-by: Dave Airlie ---- - drivers/gpu/drm/drm_fb_helper.c | 27 ++++++++++++++++++++------- - drivers/gpu/drm/i915/i915_dma.c | 2 +- - drivers/gpu/drm/i915/intel_drv.h | 1 + - drivers/gpu/drm/i915/intel_fb.c | 10 ++++++++++ - include/drm/drm_fb_helper.h | 1 + - 5 files changed, 33 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c -index 9507204..11d7a72 100644 ---- a/drivers/gpu/drm/drm_fb_helper.c -+++ b/drivers/gpu/drm/drm_fb_helper.c -@@ -342,9 +342,22 @@ int drm_fb_helper_debug_leave(struct fb_info *info) - } - EXPORT_SYMBOL(drm_fb_helper_debug_leave); - -+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) -+{ -+ bool error = false; -+ int i, ret; -+ for (i = 0; i < fb_helper->crtc_count; i++) { -+ struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; -+ ret = drm_crtc_helper_set_config(mode_set); -+ if (ret) -+ error = true; -+ } -+ return error; -+} -+EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode); -+ - bool drm_fb_helper_force_kernel_mode(void) - { -- int i = 0; - bool ret, error = false; - struct drm_fb_helper *helper; - -@@ -352,12 +365,12 @@ bool drm_fb_helper_force_kernel_mode(void) - return false; - - list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { -- for (i = 0; i < helper->crtc_count; i++) { -- struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; -- ret = drm_crtc_helper_set_config(mode_set); -- if (ret) -- error = true; -- } -+ if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF) -+ continue; -+ -+ ret = drm_fb_helper_restore_fbdev_mode(helper); -+ if (ret) -+ error = true; - } - return error; - } -diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c -index 7273037..12876f2 100644 ---- a/drivers/gpu/drm/i915/i915_dma.c -+++ b/drivers/gpu/drm/i915/i915_dma.c -@@ -2207,7 +2207,7 @@ void i915_driver_lastclose(struct drm_device * dev) - drm_i915_private_t *dev_priv = dev->dev_private; - - if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { -- drm_fb_helper_restore(); -+ intel_fb_restore_mode(dev); - vga_switcheroo_process_delayed_switch(); - return; - } -diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h -index f5b0d83..1d20712 100644 ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -338,4 +338,5 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data, - struct drm_file *file_priv); - - extern void intel_fb_output_poll_changed(struct drm_device *dev); -+extern void intel_fb_restore_mode(struct drm_device *dev); - #endif /* __INTEL_DRV_H__ */ -diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c -index 5127827..ec49bae 100644 ---- a/drivers/gpu/drm/i915/intel_fb.c -+++ b/drivers/gpu/drm/i915/intel_fb.c -@@ -264,3 +264,13 @@ void intel_fb_output_poll_changed(struct drm_device *dev) - drm_i915_private_t *dev_priv = dev->dev_private; - drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); - } -+ -+void intel_fb_restore_mode(struct drm_device *dev) -+{ -+ int ret; -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ -+ ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); -+ if (ret) -+ DRM_DEBUG("failed to restore crtc mode\n"); -+} -diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h -index f22e7fe..ade09d7 100644 ---- a/include/drm/drm_fb_helper.h -+++ b/include/drm/drm_fb_helper.h -@@ -118,6 +118,7 @@ int drm_fb_helper_setcolreg(unsigned regno, - unsigned transp, - struct fb_info *info); - -+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper); - void drm_fb_helper_restore(void); - void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, - uint32_t fb_width, uint32_t fb_height); --- -1.7.1 - From f91329b1ad750b50750ffa114d2ba750aba4bd69 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Wed, 1 Jun 2011 22:12:18 -0400 Subject: [PATCH 69/99] Revert "Delete unused intel drm patches" This reverts commit 53392f03f52c2a02804c739c35694bb1635ceb36. --- drm-intel-big-hammer.patch | 21 +++++ drm-intel-edp-fixes.patch | 44 ++++++++++ drm-intel-eeebox-eb1007-quirk.patch | 36 ++++++++ drm-intel-make-lvds-work.patch | 23 +++++ drm-intel-next.patch | 1 + drm-intel-restore-mode.patch | 128 ++++++++++++++++++++++++++++ 6 files changed, 253 insertions(+) create mode 100644 drm-intel-big-hammer.patch create mode 100644 drm-intel-edp-fixes.patch create mode 100644 drm-intel-eeebox-eb1007-quirk.patch create mode 100644 drm-intel-make-lvds-work.patch create mode 100644 drm-intel-next.patch create mode 100644 drm-intel-restore-mode.patch diff --git a/drm-intel-big-hammer.patch b/drm-intel-big-hammer.patch new file mode 100644 index 000000000..bf152af3b --- /dev/null +++ b/drm-intel-big-hammer.patch @@ -0,0 +1,21 @@ +omgwtfbbqchainsaw? +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +++++ + 1 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +index e698343..21e601d1 100644 +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -1090,6 +1090,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, + if (ret) + goto pre_mutex_err; + ++ /* We don't get the flushing right for these chipsets, use the ++ * big hammer for now to avoid random crashiness. */ ++ if (IS_I85X(dev) || IS_I865G(dev)) ++ wbinvd(); ++ + if (dev_priv->mm.suspended) { + mutex_unlock(&dev->struct_mutex); + ret = -EBUSY; diff --git a/drm-intel-edp-fixes.patch b/drm-intel-edp-fixes.patch new file mode 100644 index 000000000..c77ef116c --- /dev/null +++ b/drm-intel-edp-fixes.patch @@ -0,0 +1,44 @@ +diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c +index f737960..b1f8164 100644 +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -509,6 +509,8 @@ i915_pci_remove(struct pci_dev *pdev) + { + struct drm_device *dev = pci_get_drvdata(pdev); + ++ pci_disable_device(pdev); /* core did previous enable */ ++ + drm_put_dev(dev); + } + +diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c +index 300f64b..2e3db37 100644 +--- a/drivers/gpu/drm/i915/intel_dp.c ++++ b/drivers/gpu/drm/i915/intel_dp.c +@@ -795,7 +795,8 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) + { + struct drm_device *dev = intel_dp->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; +- u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; ++ u32 pp, idle_on = PP_ON | PP_SEQUENCE_STATE_ON_IDLE; ++ u32 idle_on_mask = PP_ON | PP_SEQUENCE_STATE_MASK; + + if (I915_READ(PCH_PP_STATUS) & PP_ON) + return true; +@@ -816,7 +817,7 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) + */ + msleep(300); + +- if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask, ++ if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on, + 5000)) + DRM_ERROR("panel on wait timed out: 0x%08x\n", + I915_READ(PCH_PP_STATUS)); +@@ -922,6 +923,7 @@ static void intel_dp_prepare(struct drm_encoder *encoder) + + if (is_edp(intel_dp)) { + ironlake_edp_backlight_off(dev); ++ ironlake_edp_panel_off(dev); + ironlake_edp_panel_on(intel_dp); + if (!is_pch_edp(intel_dp)) + ironlake_edp_pll_on(encoder); diff --git a/drm-intel-eeebox-eb1007-quirk.patch b/drm-intel-eeebox-eb1007-quirk.patch new file mode 100644 index 000000000..9ae3604e7 --- /dev/null +++ b/drm-intel-eeebox-eb1007-quirk.patch @@ -0,0 +1,36 @@ +From ab737b006568d01204cc51368c7e2067eecb2cff Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 7 Apr 2011 13:31:57 +0200 +Subject: [PATCH] drm/i915: Add a no lvds quirk for the Asus EeeBox PC EB1007 + +I found this while figuring out why gnome-shell would not run on my +Asus EeeBox PC EB1007. As a standalone "pc" this device cleary does not have +an internal panel, yet it claims it does. Add a quirk to fix this. + +Signed-off-by: Hans de Goede +--- + drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ + 1 files changed, 8 insertions(+), 0 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index a562bd2..954822a 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -724,6 +724,14 @@ static const struct dmi_system_id intel_no_lvds[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "U800"), + }, + }, ++ { ++ .callback = intel_no_lvds_dmi_callback, ++ .ident = "Asus EeeBox PC EB1007", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), ++ }, ++ }, + + { } /* terminating entry */ + }; +-- +1.7.4.2 + diff --git a/drm-intel-make-lvds-work.patch b/drm-intel-make-lvds-work.patch new file mode 100644 index 000000000..209deb295 --- /dev/null +++ b/drm-intel-make-lvds-work.patch @@ -0,0 +1,23 @@ + drivers/gpu/drm/i915/intel_display.c | 2 -- + 1 files changed, 0 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 990f065..171a797 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -4568,7 +4568,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, + struct drm_connector *connector, int dpms_mode) + { + struct drm_encoder *encoder = &intel_encoder->base; +- struct drm_device *dev = encoder->dev; + struct drm_crtc *crtc = encoder->crtc; + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; +@@ -4578,7 +4577,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, + connector->encoder = NULL; + intel_encoder->load_detect_temp = false; + crtc->enabled = drm_helper_crtc_in_use(crtc); +- drm_helper_disable_unused_functions(dev); + } + + /* Switch crtc and encoder back off if necessary */ diff --git a/drm-intel-next.patch b/drm-intel-next.patch new file mode 100644 index 000000000..c6cac6926 --- /dev/null +++ b/drm-intel-next.patch @@ -0,0 +1 @@ +empty diff --git a/drm-intel-restore-mode.patch b/drm-intel-restore-mode.patch new file mode 100644 index 000000000..b394ca00d --- /dev/null +++ b/drm-intel-restore-mode.patch @@ -0,0 +1,128 @@ +From e8e7a2b8ccfdae0d4cb6bd25824bbedcd42da316 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Thu, 21 Apr 2011 22:18:32 +0100 +Subject: [PATCH] drm/i915: restore only the mode of this driver on lastclose (v2) + +i915 calls the panic handler function on last close to reset the modes, +however this is a really bad idea for multi-gpu machines, esp shareable +gpus machines. So add a new entry point for the driver to just restore +its own fbcon mode. + +v2: move code into fb helper, fix panic code to block mode change on +powered off GPUs. + +[airlied: this hits drm core and I wrote it and it was reviewed on intel-gfx + so really I signed it off twice ;-).] +Signed-off-by: Chris Wilson +Signed-off-by: Dave Airlie +--- + drivers/gpu/drm/drm_fb_helper.c | 27 ++++++++++++++++++++------- + drivers/gpu/drm/i915/i915_dma.c | 2 +- + drivers/gpu/drm/i915/intel_drv.h | 1 + + drivers/gpu/drm/i915/intel_fb.c | 10 ++++++++++ + include/drm/drm_fb_helper.h | 1 + + 5 files changed, 33 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c +index 9507204..11d7a72 100644 +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -342,9 +342,22 @@ int drm_fb_helper_debug_leave(struct fb_info *info) + } + EXPORT_SYMBOL(drm_fb_helper_debug_leave); + ++bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) ++{ ++ bool error = false; ++ int i, ret; ++ for (i = 0; i < fb_helper->crtc_count; i++) { ++ struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; ++ ret = drm_crtc_helper_set_config(mode_set); ++ if (ret) ++ error = true; ++ } ++ return error; ++} ++EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode); ++ + bool drm_fb_helper_force_kernel_mode(void) + { +- int i = 0; + bool ret, error = false; + struct drm_fb_helper *helper; + +@@ -352,12 +365,12 @@ bool drm_fb_helper_force_kernel_mode(void) + return false; + + list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { +- for (i = 0; i < helper->crtc_count; i++) { +- struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; +- ret = drm_crtc_helper_set_config(mode_set); +- if (ret) +- error = true; +- } ++ if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF) ++ continue; ++ ++ ret = drm_fb_helper_restore_fbdev_mode(helper); ++ if (ret) ++ error = true; + } + return error; + } +diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c +index 7273037..12876f2 100644 +--- a/drivers/gpu/drm/i915/i915_dma.c ++++ b/drivers/gpu/drm/i915/i915_dma.c +@@ -2207,7 +2207,7 @@ void i915_driver_lastclose(struct drm_device * dev) + drm_i915_private_t *dev_priv = dev->dev_private; + + if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { +- drm_fb_helper_restore(); ++ intel_fb_restore_mode(dev); + vga_switcheroo_process_delayed_switch(); + return; + } +diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h +index f5b0d83..1d20712 100644 +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -338,4 +338,5 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data, + struct drm_file *file_priv); + + extern void intel_fb_output_poll_changed(struct drm_device *dev); ++extern void intel_fb_restore_mode(struct drm_device *dev); + #endif /* __INTEL_DRV_H__ */ +diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c +index 5127827..ec49bae 100644 +--- a/drivers/gpu/drm/i915/intel_fb.c ++++ b/drivers/gpu/drm/i915/intel_fb.c +@@ -264,3 +264,13 @@ void intel_fb_output_poll_changed(struct drm_device *dev) + drm_i915_private_t *dev_priv = dev->dev_private; + drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); + } ++ ++void intel_fb_restore_mode(struct drm_device *dev) ++{ ++ int ret; ++ drm_i915_private_t *dev_priv = dev->dev_private; ++ ++ ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); ++ if (ret) ++ DRM_DEBUG("failed to restore crtc mode\n"); ++} +diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h +index f22e7fe..ade09d7 100644 +--- a/include/drm/drm_fb_helper.h ++++ b/include/drm/drm_fb_helper.h +@@ -118,6 +118,7 @@ int drm_fb_helper_setcolreg(unsigned regno, + unsigned transp, + struct fb_info *info); + ++bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper); + void drm_fb_helper_restore(void); + void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, + uint32_t fb_width, uint32_t fb_height); +-- +1.7.1 + From 18dd18f538f7b7e3a79d7e6c6a6697aff86596a0 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 4 Jun 2011 10:57:43 -0400 Subject: [PATCH 70/99] Linux 2.6.38.8 Revert radeon patches we already have: drm/radeon/kms: add wait idle ioctl for eg->cayman drm/radeon/evergreen/btc/fusion: setup hdp to invalidate and flush when asked Drop individual patches we have: ips-use-interruptible-waits-in-ips-monitor.patch drm-vblank-events-fix-hangs.patch mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch --- .gitignore | 1 + drm-vblank-events-fix-hangs.patch | 60 ------- ...e-interruptible-waits-in-ips-monitor.patch | 30 ---- kernel.spec | 33 ++-- linux-2.6-upstream-reverts.patch | 104 ++++++++++++ ...dat_balanced-in-sleeping_prematurely.patch | 114 ------------- ...r-should-schedule-during-shrink_slab.patch | 153 ------------------ sources | 2 +- 8 files changed, 119 insertions(+), 378 deletions(-) delete mode 100644 drm-vblank-events-fix-hangs.patch delete mode 100644 ips-use-interruptible-waits-in-ips-monitor.patch delete mode 100644 mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch delete mode 100644 mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch diff --git a/.gitignore b/.gitignore index c2fd41347..8043b138c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ patch-*.bz2 clog *.rpm kernel-2.6.*/ +kernel-3.*/ diff --git a/drm-vblank-events-fix-hangs.patch b/drm-vblank-events-fix-hangs.patch deleted file mode 100644 index 1148f4e3c..000000000 --- a/drm-vblank-events-fix-hangs.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 498548ec69c6897fe4376b2ca90758762fa0b817 Mon Sep 17 00:00:00 2001 -From: Christopher James Halse Rogers -Date: Wed, 27 Apr 2011 16:10:57 +1000 -Subject: [PATCH 3/4] drm: Send pending vblank events before disabling vblank. - -This is the least-bad behaviour. It means that we signal the -vblank event before it actually happens, but since we're disabling -vblanks there's no guarantee that it will *ever* happen otherwise. - -This prevents GL applications which use WaitMSC from hanging -indefinitely. - -Signed-off-by: Christopher James Halse Rogers -Signed-off-by: Dave Airlie ---- - drivers/gpu/drm/drm_irq.c | 23 +++++++++++++++++++++++ - 1 files changed, 23 insertions(+), 0 deletions(-) - -diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c -index 741457b..a1f12cb 100644 ---- a/drivers/gpu/drm/drm_irq.c -+++ b/drivers/gpu/drm/drm_irq.c -@@ -932,11 +932,34 @@ EXPORT_SYMBOL(drm_vblank_put); - - void drm_vblank_off(struct drm_device *dev, int crtc) - { -+ struct drm_pending_vblank_event *e, *t; -+ struct timeval now; - unsigned long irqflags; -+ unsigned int seq; - - spin_lock_irqsave(&dev->vbl_lock, irqflags); - vblank_disable_and_save(dev, crtc); - DRM_WAKEUP(&dev->vbl_queue[crtc]); -+ -+ /* Send any queued vblank events, lest the natives grow disquiet */ -+ seq = drm_vblank_count_and_time(dev, crtc, &now); -+ list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { -+ if (e->pipe != crtc) -+ continue; -+ DRM_DEBUG("Sending premature vblank event on disable: \ -+ wanted %d, current %d\n", -+ e->event.sequence, seq); -+ -+ e->event.sequence = seq; -+ e->event.tv_sec = now.tv_sec; -+ e->event.tv_usec = now.tv_usec; -+ drm_vblank_put(dev, e->pipe); -+ list_move_tail(&e->base.link, &e->base.file_priv->event_list); -+ wake_up_interruptible(&e->base.file_priv->event_wait); -+ trace_drm_vblank_event_delivered(e->base.pid, e->pipe, -+ e->event.sequence); -+ } -+ - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - } - EXPORT_SYMBOL(drm_vblank_off); --- -1.7.1 - diff --git a/ips-use-interruptible-waits-in-ips-monitor.patch b/ips-use-interruptible-waits-in-ips-monitor.patch deleted file mode 100644 index dbea1a1a0..000000000 --- a/ips-use-interruptible-waits-in-ips-monitor.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Jesse Barnes -Date: Mon, 28 Mar 2011 10:36:30 +0000 (-0400) -Subject: ips: use interruptible waits in ips-monitor -X-Git-Tag: v2.6.39-rc1~20^2^2~1 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=a3424216e4935221fdaa5ca3c26e024f11297164 - -ips: use interruptible waits in ips-monitor - -This is what I intended to do since: - 1) the driver handles variable waits just fine, and - 2) interruptible waits aren't reported as load in the load avg. - -Reported-and-tested-by: Andreas Hartmann -Signed-off-by: Jesse Barnes -Signed-off-by: Matthew Garrett ---- - -diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c -index 1294a39..85c8ad4 100644 ---- a/drivers/platform/x86/intel_ips.c -+++ b/drivers/platform/x86/intel_ips.c -@@ -1111,7 +1111,7 @@ static int ips_monitor(void *data) - last_msecs = jiffies_to_msecs(jiffies); - expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD); - -- __set_current_state(TASK_UNINTERRUPTIBLE); -+ __set_current_state(TASK_INTERRUPTIBLE); - mod_timer(&timer, expire); - schedule(); - diff --git a/kernel.spec b/kernel.spec index 43c23524c..52ead69ff 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 30 +%global baserelease 31 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -63,7 +63,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 7 +%define stable_update 8 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -668,7 +668,6 @@ Patch800: linux-2.6-crash-driver.patch Patch1555: fix_xen_guest_on_old_EC2.patch # DRM -Patch1800: drm-vblank-events-fix-hangs.patch # nouveau + drm fixes Patch1809: drm-nouveau-fixes.patch @@ -743,19 +742,11 @@ Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-availabl # Fix breakage of PCI network adapter names on older Dell systems Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch -# intel_ips driver bug (#703511) causes cooling fan to run -Patch12406: ips-use-interruptible-waits-in-ips-monitor.patch - Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch # temporary fix for Sempron machines stalling (#704059) Patch12408: x86-amd-arat-bug-on-sempron-workaround.patch -# Eliminate hangs when using frequent high-order allocations V4 -# (will be in 2.6.38.8) -Patch12410: mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch -Patch12411: mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch - Patch12415: hid-multitouch-add-support-for-elo-touchsystems.patch Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch @@ -1326,7 +1317,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core -ApplyPatch drm-vblank-events-fix-hangs.patch # Nouveau DRM ApplyPatch drm-ttm-move-notify.patch @@ -1395,19 +1385,11 @@ ApplyPatch linux-2.6-netconsole-deadlock.patch # CVE-2011-1581 ApplyPatch bonding-incorrect-tx-queue-offset.patch -# intel_ips driver bug (#703511) causes cooling fan to run -ApplyPatch ips-use-interruptible-waits-in-ips-monitor.patch - ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch # temporary fix for Sempron machines stalling (#704059) ApplyPatch x86-amd-arat-bug-on-sempron-workaround.patch -# Eliminate hangs when using frequent high-order allocations V4 -# (will be in 2.6.38.8) -ApplyPatch mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch -ApplyPatch mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch - ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch @@ -2019,6 +2001,17 @@ fi # and build. %changelog +* Sat Jun 04 2011 Chuck Ebbert 2.6.38.8-31 +- Linux 2.6.38.8 +- Revert radeon patches we already have: + drm/radeon/kms: add wait idle ioctl for eg->cayman + drm/radeon/evergreen/btc/fusion: setup hdp to invalidate and flush when asked +- Drop individual patches we have: + ips-use-interruptible-waits-in-ips-monitor.patch + drm-vblank-events-fix-hangs.patch + mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch + mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch + * Sun May 29 2011 Dave Airlie - fix oops on pageflipping sometimes (#680651) diff --git a/linux-2.6-upstream-reverts.patch b/linux-2.6-upstream-reverts.patch index a8ec0e390..157205fb2 100644 --- a/linux-2.6-upstream-reverts.patch +++ b/linux-2.6-upstream-reverts.patch @@ -1,3 +1,107 @@ +From 97bfd0acd32e9639c9136e03955d574655d5cc2b Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Thu, 19 May 2011 14:14:43 +1000 +Subject: drm/radeon/kms: add wait idle ioctl for eg->cayman + +From: Dave Airlie + +commit 97bfd0acd32e9639c9136e03955d574655d5cc2b upstream. + +None of the latest GPUs had this hooked up, this is necessary for +correct operation in a lot of cases, however we should test this on a few +GPUs in these families as we've had problems in this area before. + +Reviewed-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_asic.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -782,6 +782,7 @@ static struct radeon_asic evergreen_asic + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, +@@ -828,6 +829,7 @@ static struct radeon_asic sumo_asic = { + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, +@@ -874,6 +876,8 @@ static struct radeon_asic btc_asic = { + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, ++ .ioctl_wait_idle = r600_ioctl_wait_idle, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, +From f25a5c63bfa017498c9adecb24d649ae96ba5c68 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 19 May 2011 11:07:57 -0400 +Subject: drm/radeon/evergreen/btc/fusion: setup hdp to invalidate and + flush when asked + +From: Alex Deucher + +commit f25a5c63bfa017498c9adecb24d649ae96ba5c68 upstream. + +This needs to be explicitly set on btc. It's set by default +on evergreen/fusion, so it fine to just unconditionally enable it for +all chips. + +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen.c | 6 +++++- + drivers/gpu/drm/radeon/evergreend.h | 2 ++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1585,7 +1585,7 @@ static void evergreen_gpu_init(struct ra + u32 sq_stack_resource_mgmt_2; + u32 sq_stack_resource_mgmt_3; + u32 vgt_cache_invalidation; +- u32 hdp_host_path_cntl; ++ u32 hdp_host_path_cntl, tmp; + int i, j, num_shader_engines, ps_thread_count; + + switch (rdev->family) { +@@ -2145,6 +2145,10 @@ static void evergreen_gpu_init(struct ra + for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) + WREG32(i, 0); + ++ tmp = RREG32(HDP_MISC_CNTL); ++ tmp |= HDP_FLUSH_INVALIDATE_CACHE; ++ WREG32(HDP_MISC_CNTL, tmp); ++ + hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); + WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); + +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -64,6 +64,8 @@ + #define GB_BACKEND_MAP 0x98FC + #define DMIF_ADDR_CONFIG 0xBD4 + #define HDP_ADDR_CONFIG 0x2F48 ++#define HDP_MISC_CNTL 0x2F4C ++#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) + + #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 + #define GC_USER_RB_BACKEND_DISABLE 0x9B7C From alexdeucher@gmail.com Mon May 9 16:35:34 2011 From: Alex Deucher Date: Fri, 6 May 2011 14:29:55 -0400 diff --git a/mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch b/mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch deleted file mode 100644 index a619a59ad..000000000 --- a/mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch +++ /dev/null @@ -1,114 +0,0 @@ -Return-Path: stable-bounces@linux.kernel.org -Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO - zmta03.collab.prod.int.phx2.redhat.com) (10.5.5.33) by - mail02.corp.redhat.com with LMTP; Mon, 23 May 2011 05:54:46 -0400 (EDT) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 3139D4E5E6 - for ; Mon, 23 May 2011 05:54:46 -0400 (EDT) -Received: from zmta03.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta03.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id Xko2+8bJJ7po for ; - Mon, 23 May 2011 05:54:46 -0400 (EDT) -Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) - by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 1A5854D284 - for ; Mon, 23 May 2011 05:54:46 -0400 (EDT) -Received: from mx1.redhat.com (ext-mx13.extmail.prod.ext.phx2.redhat.com [10.5.110.18]) - by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p4N9sjdi005829 - for ; Mon, 23 May 2011 05:54:45 -0400 -Received: from hera.kernel.org (hera.kernel.org [140.211.167.34]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4N9siLf018408 - for ; Mon, 23 May 2011 05:54:45 -0400 -Received: from hera.kernel.org (localhost [127.0.0.1]) - by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9s7Yv010104; - Mon, 23 May 2011 09:54:09 GMT -X-Virus-Status: Clean -X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org -Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) - by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9s1LC009736; - Mon, 23 May 2011 09:54:02 GMT -X-Virus-Status: Clean -X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org -Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) - by mx2.suse.de (Postfix) with ESMTP id 98E7590072; - Mon, 23 May 2011 11:53:59 +0200 (CEST) -From: Mel Gorman -To: Andrew Morton -Date: Mon, 23 May 2011 10:53:54 +0100 -Message-Id: <1306144435-2516-2-git-send-email-mgorman@suse.de> -In-Reply-To: <1306144435-2516-1-git-send-email-mgorman@suse.de> -References: <1306144435-2516-1-git-send-email-mgorman@suse.de> -X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED - autolearn=unavailable version=3.3.2-r929478 -X-Spam-Checker-Version: SpamAssassin 3.3.2-r929478 (2010-03-31) on - hera.kernel.org -X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.2.3 (hera.kernel.org [127.0.0.1]); Mon, 23 May 2011 09:54:12 +0000 (UTC) -X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by - milter-greylist-4.2.3 (hera.kernel.org [140.211.167.34]); - Mon, 23 May 2011 09:54:04 +0000 (UTC) -Cc: Pekka Enberg , Rik van Riel , - Jan Kara , linux-kernel , - James Bottomley , - linux-mm , Minchan Kim , - Raghavendra D Prabhu , - Johannes Weiner , - linux-fsdevel , - Colin King , - Christoph Lameter , - linux-ext4 , stable , - Chris Mason , Mel Gorman -Subject: [stable] [PATCH 1/2] mm: vmscan: Correct use of pgdat_balanced in - sleeping_prematurely -X-BeenThere: stable@linux.kernel.org -X-Mailman-Version: 2.1.12 -Precedence: list -List-Id: For maintainers of the stable Linux series -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -MIME-Version: 1.0 -Content-Type: text/plain; charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: stable-bounces@linux.kernel.org -Errors-To: stable-bounces@linux.kernel.org -X-RedHat-Spam-Score: -2.31 (RCVD_IN_DNSWL_MED,T_RP_MATCHES_RCVD) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 -X-Scanned-By: MIMEDefang 2.68 on 10.5.110.18 - -From: Johannes Weiner - -Johannes Weiner poined out that the logic in commit [1741c877: mm: -kswapd: keep kswapd awake for high-order allocations until a percentage -of the node is balanced] is backwards. Instead of allowing kswapd to go -to sleep when balancing for high order allocations, it keeps it kswapd -running uselessly. - -Signed-off-by: Mel Gorman -Reviewed-by: Rik van Riel ---- - mm/vmscan.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/mm/vmscan.c b/mm/vmscan.c -index 8bfd450..1aa262b 100644 ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -2286,7 +2286,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining, - * must be balanced - */ - if (order) -- return pgdat_balanced(pgdat, balanced, classzone_idx); -+ return !pgdat_balanced(pgdat, balanced, classzone_idx); - else - return !all_zones_ok; - } --- -1.7.3.4 - -_______________________________________________ -stable mailing list -stable@linux.kernel.org -http://linux.kernel.org/mailman/listinfo/stable diff --git a/mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch b/mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch deleted file mode 100644 index b5b053eac..000000000 --- a/mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch +++ /dev/null @@ -1,153 +0,0 @@ -Return-Path: stable-bounces@linux.kernel.org -Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO - zmta01.collab.prod.int.phx2.redhat.com) (10.5.5.31) by - mail02.corp.redhat.com with LMTP; Mon, 23 May 2011 05:54:49 -0400 (EDT) -Received: from localhost (localhost.localdomain [127.0.0.1]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 443AC9289D - for ; Mon, 23 May 2011 05:54:49 -0400 (EDT) -Received: from zmta01.collab.prod.int.phx2.redhat.com ([127.0.0.1]) - by localhost (zmta01.collab.prod.int.phx2.redhat.com [127.0.0.1]) (amavisd-new, port 10024) - with ESMTP id WTG56s2uAm8Z for ; - Mon, 23 May 2011 05:54:49 -0400 (EDT) -Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) - by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 2D1D2906E4 - for ; Mon, 23 May 2011 05:54:49 -0400 (EDT) -Received: from mx1.redhat.com (ext-mx11.extmail.prod.ext.phx2.redhat.com [10.5.110.16]) - by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p4N9snmk002150 - for ; Mon, 23 May 2011 05:54:49 -0400 -Received: from hera.kernel.org (hera.kernel.org [140.211.167.34]) - by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4N9smZs008302 - for ; Mon, 23 May 2011 05:54:48 -0400 -Received: from hera.kernel.org (localhost [127.0.0.1]) - by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9sGZo010150; - Mon, 23 May 2011 09:54:16 GMT -X-Virus-Status: Clean -X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org -Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) - by hera.kernel.org (8.14.4/8.14.3) with ESMTP id p4N9s1xm009737; - Mon, 23 May 2011 09:54:02 GMT -X-Virus-Status: Clean -X-Virus-Scanned: clamav-milter 0.97 at hera.kernel.org -Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) - by mx2.suse.de (Postfix) with ESMTP id 2B4998FFEB; - Mon, 23 May 2011 11:54:01 +0200 (CEST) -From: Mel Gorman -To: Andrew Morton -Date: Mon, 23 May 2011 10:53:55 +0100 -Message-Id: <1306144435-2516-3-git-send-email-mgorman@suse.de> -In-Reply-To: <1306144435-2516-1-git-send-email-mgorman@suse.de> -References: <1306144435-2516-1-git-send-email-mgorman@suse.de> -X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED - autolearn=unavailable version=3.3.2-r929478 -X-Spam-Checker-Version: SpamAssassin 3.3.2-r929478 (2010-03-31) on - hera.kernel.org -X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.2.3 (hera.kernel.org [127.0.0.1]); Mon, 23 May 2011 09:54:16 +0000 (UTC) -X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by - milter-greylist-4.2.3 (hera.kernel.org [140.211.167.34]); - Mon, 23 May 2011 09:54:03 +0000 (UTC) -Cc: Pekka Enberg , Rik van Riel , - Jan Kara , linux-kernel , - James Bottomley , - linux-mm , Minchan Kim , - Raghavendra D Prabhu , - Johannes Weiner , - linux-fsdevel , - Colin King , - Christoph Lameter , - linux-ext4 , stable , - Chris Mason , Mel Gorman -Subject: [stable] [PATCH 2/2] mm: vmscan: Correctly check if reclaimer - should schedule during shrink_slab -X-BeenThere: stable@linux.kernel.org -X-Mailman-Version: 2.1.12 -Precedence: list -List-Id: For maintainers of the stable Linux series -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -MIME-Version: 1.0 -Content-Type: text/plain; charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: stable-bounces@linux.kernel.org -Errors-To: stable-bounces@linux.kernel.org -X-RedHat-Spam-Score: -2.31 (RCVD_IN_DNSWL_MED,T_RP_MATCHES_RCVD) -X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 -X-Scanned-By: MIMEDefang 2.68 on 10.5.110.16 - -It has been reported on some laptops that kswapd is consuming large -amounts of CPU and not being scheduled when SLUB is enabled during -large amounts of file copying. It is expected that this is due to -kswapd missing every cond_resched() point because; - -shrink_page_list() calls cond_resched() if inactive pages were isolated - which in turn may not happen if all_unreclaimable is set in - shrink_zones(). If for whatver reason, all_unreclaimable is - set on all zones, we can miss calling cond_resched(). - -balance_pgdat() only calls cond_resched if the zones are not - balanced. For a high-order allocation that is balanced, it - checks order-0 again. During that window, order-0 might have - become unbalanced so it loops again for order-0 and returns - that it was reclaiming for order-0 to kswapd(). It can then - find that a caller has rewoken kswapd for a high-order and - re-enters balance_pgdat() without ever calling cond_resched(). - -shrink_slab only calls cond_resched() if we are reclaiming slab - pages. If there are a large number of direct reclaimers, the - shrinker_rwsem can be contended and prevent kswapd calling - cond_resched(). - -This patch modifies the shrink_slab() case. If the semaphore is -contended, the caller will still check cond_resched(). After each -successful call into a shrinker, the check for cond_resched() remains -in case one shrinker is particularly slow. - -This patch replaces -mm-vmscan-if-kswapd-has-been-running-too-long-allow-it-to-sleep.patch -in -mm. - -[mgorman@suse.de: Preserve call to cond_resched after each call into shrinker] -From: Minchan Kim -Signed-off-by: Mel Gorman ---- - mm/vmscan.c | 9 +++++++-- - 1 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/mm/vmscan.c b/mm/vmscan.c -index 1aa262b..cc1470b 100644 ---- a/mm/vmscan.c -+++ b/mm/vmscan.c -@@ -230,8 +230,11 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, - if (scanned == 0) - scanned = SWAP_CLUSTER_MAX; - -- if (!down_read_trylock(&shrinker_rwsem)) -- return 1; /* Assume we'll be able to shrink next time */ -+ if (!down_read_trylock(&shrinker_rwsem)) { -+ /* Assume we'll be able to shrink next time */ -+ ret = 1; -+ goto out; -+ } - - list_for_each_entry(shrinker, &shrinker_list, list) { - unsigned long long delta; -@@ -282,6 +285,8 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, - shrinker->nr += total_scan; - } - up_read(&shrinker_rwsem); -+out: -+ cond_resched(); - return ret; - } - --- -1.7.3.4 - -_______________________________________________ -stable mailing list -stable@linux.kernel.org -http://linux.kernel.org/mailman/listinfo/stable diff --git a/sources b/sources index b582c97ed..b519133bb 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -2639b4b98a2dcfc8b7f091543f289205 patch-2.6.38.7.bz2 +c0f416f6a2e916633f697287cc7cb914 patch-2.6.38.8.bz2 From f6de3b43404a7bcaadbde2c8dae7562ca22518f8 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 4 Jun 2011 11:06:11 -0400 Subject: [PATCH 71/99] Drop AMD timer workaround; the proper fix is in 2.6.38.8 --- kernel.spec | 7 +------ x86-amd-arat-bug-on-sempron-workaround.patch | 18 ------------------ 2 files changed, 1 insertion(+), 24 deletions(-) delete mode 100644 x86-amd-arat-bug-on-sempron-workaround.patch diff --git a/kernel.spec b/kernel.spec index 52ead69ff..204317de3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -744,9 +744,6 @@ Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patc Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch -# temporary fix for Sempron machines stalling (#704059) -Patch12408: x86-amd-arat-bug-on-sempron-workaround.patch - Patch12415: hid-multitouch-add-support-for-elo-touchsystems.patch Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch @@ -1387,9 +1384,6 @@ ApplyPatch bonding-incorrect-tx-queue-offset.patch ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch -# temporary fix for Sempron machines stalling (#704059) -ApplyPatch x86-amd-arat-bug-on-sempron-workaround.patch - ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch @@ -2011,6 +2005,7 @@ fi drm-vblank-events-fix-hangs.patch mm-vmscan-correct-use-of-pgdat_balanced-in-sleeping_prematurely.patch mm-vmscan-correctly-check-if-reclaimer-should-schedule-during-shrink_slab.patch +- Drop x86-amd-arat-bug-on-sempron-workaround.patch; the proper fix is in 2.6.38.8 * Sun May 29 2011 Dave Airlie - fix oops on pageflipping sometimes (#680651) diff --git a/x86-amd-arat-bug-on-sempron-workaround.patch b/x86-amd-arat-bug-on-sempron-workaround.patch deleted file mode 100644 index 262293b00..000000000 --- a/x86-amd-arat-bug-on-sempron-workaround.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/arch/x86/kernel/cpu/amd.c -+++ b/arch/x86/kernel/cpu/amd.c -@@ -724,6 +724,15 @@ bool cpu_has_amd_erratum(const int *erra - if (cpu->x86_vendor != X86_VENDOR_AMD) - return false; - -+ /* -+ * Temporary workaround for ARAT bug on Sempron. -+ * The BIOS clears the bit in OSVW, so the check -+ * fails, then ARAT gets set and when the processor -+ * uses C3 it hangs. Always return true for that CPU. -+ */ -+ if (cpu->x86 == 0x10 && cpu->x86_model == 6 && cpu->x86_mask == 2) -+ return true; -+ - if (osvw_id >= 0 && osvw_id < 65536 && - cpu_has(cpu, X86_FEATURE_OSVW)) { - u64 osvw_len; From 0b2fda5000b7294349276db6e09f0ba4dd92bf4e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 7 Jun 2011 15:25:58 -0400 Subject: [PATCH 72/99] [SCSI] Fix oops caused by queue refcounting failure --- block-queue-refcount.patch | 43 ++++++++++++++++++++++++++++++++++++++ kernel.spec | 6 ++++++ 2 files changed, 49 insertions(+) create mode 100644 block-queue-refcount.patch diff --git a/block-queue-refcount.patch b/block-queue-refcount.patch new file mode 100644 index 000000000..d53dd1bac --- /dev/null +++ b/block-queue-refcount.patch @@ -0,0 +1,43 @@ +commit e73e079bf128d68284efedeba1fbbc18d78610f9 +Author: James Bottomley +Date: Wed May 25 15:52:14 2011 -0500 + + [SCSI] Fix oops caused by queue refcounting failure + + In certain circumstances, we can get an oops from a torn down device. + Most notably this is from CD roms trying to call scsi_ioctl. The root + cause of the problem is the fact that after scsi_remove_device() has + been called, the queue is fully torn down. This is actually wrong + since the queue can be used until the sdev release function is called. + Therefore, we add an extra reference to the queue which is released in + sdev->release, so the queue always exists. + + Reported-by: Parag Warudkar + Cc: stable@kernel.org + Signed-off-by: James Bottomley + +diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c +index 58584dc..44e8ca3 100644 +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -297,7 +297,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, + kfree(sdev); + goto out; + } +- ++ blk_get_queue(sdev->request_queue); + sdev->request_queue->queuedata = sdev; + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + +diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c +index e639125..e0bd3f7 100644 +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -322,6 +322,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) + kfree(evt); + } + ++ blk_put_queue(sdev->request_queue); + /* NULL queue means the device can't be used */ + sdev->request_queue = NULL; + diff --git a/kernel.spec b/kernel.spec index 204317de3..06756f1be 100644 --- a/kernel.spec +++ b/kernel.spec @@ -656,6 +656,8 @@ Patch530: linux-2.6-silence-fbcon-logo.patch Patch570: linux-2.6-selinux-mprotect-checks.patch Patch580: linux-2.6-sparc-selinux-mprotect-checks.patch +Patch600: block-queue-refcount.patch + Patch610: hda_intel-prealloc-4mb-dmabuffer.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -1267,6 +1269,7 @@ ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch # # SCSI Bits. # +ApplyPatch block-queue-refcount.patch # ACPI @@ -1995,6 +1998,9 @@ fi # and build. %changelog +* Tue Jun 07 2011 Dave Jones +- [SCSI] Fix oops caused by queue refcounting failure. + * Sat Jun 04 2011 Chuck Ebbert 2.6.38.8-31 - Linux 2.6.38.8 - Revert radeon patches we already have: From b97a14431d4501b08019453dce4a34753ad064fb Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 7 Jun 2011 15:30:02 -0400 Subject: [PATCH 73/99] oops, need to export these for the previous block patch to compile. --- block-queue-refcount.patch | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/block-queue-refcount.patch b/block-queue-refcount.patch index d53dd1bac..c0f09a45a 100644 --- a/block-queue-refcount.patch +++ b/block-queue-refcount.patch @@ -41,3 +41,21 @@ index e639125..e0bd3f7 100644 /* NULL queue means the device can't be used */ sdev->request_queue = NULL; +--- linux-2.6.38.noarch/block/blk-core.c~ 2011-06-07 15:29:26.000000000 -0400 ++++ linux-2.6.38.noarch/block/blk-core.c 2011-06-07 15:29:49.000000000 -0400 +@@ -456,6 +456,7 @@ void blk_put_queue(struct request_queue + { + kobject_put(&q->kobj); + } ++EXPORT_SYMBOL(blk_put_queue); + + void blk_cleanup_queue(struct request_queue *q) + { +@@ -663,6 +664,7 @@ int blk_get_queue(struct request_queue * + + return 1; + } ++EXPORT_SYMBOL(blk_get_queue); + + static inline void blk_free_request(struct request_queue *q, struct request *rq) + { From 8dba4a6f78b8fd57570fcf5f9b5af7428cd1ae60 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 9 Jun 2011 10:45:09 -0400 Subject: [PATCH 74/99] ath5k-disable-fast-channel-switching-by-default.patch (rhbz#709122) (korgbz#34992) [a99168ee in wireless-next] --- ...le-fast-channel-switching-by-default.patch | 72 +++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 81 insertions(+) create mode 100644 ath5k-disable-fast-channel-switching-by-default.patch diff --git a/ath5k-disable-fast-channel-switching-by-default.patch b/ath5k-disable-fast-channel-switching-by-default.patch new file mode 100644 index 000000000..86ebf8340 --- /dev/null +++ b/ath5k-disable-fast-channel-switching-by-default.patch @@ -0,0 +1,72 @@ +From c564db51fe187362c4da0a9de2905c020e981c75 Mon Sep 17 00:00:00 2001 +From: Nick Kossifidis +Date: Thu, 2 Jun 2011 03:09:48 +0300 +Subject: ath5k: Disable fast channel switching by default + +Disable fast channel change by default on AR2413/AR5413 due to +some bug reports (it still works for me but it's better to be safe). +Add a module parameter "fastchanswitch" in case anyone wants to enable +it and play with it. + +Signed-off-by: Nick Kossifidis +Tested-by: Sedat Dilek +Signed-off-by: John W. Linville +--- + drivers/net/wireless/ath/ath5k/base.c | 9 ++++++++- + drivers/net/wireless/ath/ath5k/reset.c | 5 ++++- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c +index 09ae4ef..0fb6333 100644 +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -69,6 +69,11 @@ static int modparam_all_channels; + module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); + MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); + ++static int modparam_fastchanswitch; ++module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); ++MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); ++ ++ + /* Module info */ + MODULE_AUTHOR("Jiri Slaby"); + MODULE_AUTHOR("Nick Kossifidis"); +@@ -2664,6 +2669,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + struct ath5k_hw *ah = sc->ah; + struct ath_common *common = ath5k_hw_common(ah); + int ret, ani_mode; ++ bool fast; + + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); + +@@ -2685,7 +2691,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, + sc->curchan = chan; + sc->curband = &sc->sbands[chan->band]; + } +- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, ++ fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; ++ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, + skip_pcu); + if (ret) { + ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); +diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c +index 8420689..6f53d2b 100644 +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -1119,8 +1119,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + /* Non fatal, can happen eg. + * on mode change */ + ret = 0; +- } else ++ } else { ++ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, ++ "fast chan change successful\n"); + return 0; ++ } + } + + /* +-- +1.7.5.2 + diff --git a/kernel.spec b/kernel.spec index 06756f1be..391f0e9e1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -749,6 +749,8 @@ Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch Patch12415: hid-multitouch-add-support-for-elo-touchsystems.patch Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch +Patch12418: ath5k-disable-fast-channel-switching-by-default.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1390,6 +1392,9 @@ ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch +# rhbz#709122 +ApplyPatch ath5k-disable-fast-channel-switching-by-default.patch + # END OF PATCH APPLICATIONS %endif @@ -1998,6 +2003,10 @@ fi # and build. %changelog +* Thu Jun 09 2011 Kyle McMartin +- ath5k-disable-fast-channel-switching-by-default.patch (rhbz#709122) + (korgbz#34992) [a99168ee in wireless-next] + * Tue Jun 07 2011 Dave Jones - [SCSI] Fix oops caused by queue refcounting failure. From bfdadc2f0b622d349f62ef083c8fd369bea0129e Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 13 Jun 2011 15:25:44 -0400 Subject: [PATCH 75/99] bump baserelease for a build (to fix this elv_completed_request bug) --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 391f0e9e1..465a8bf7e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 31 +%global baserelease 32 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2003,7 +2003,7 @@ fi # and build. %changelog -* Thu Jun 09 2011 Kyle McMartin +* Thu Jun 09 2011 Kyle McMartin 2.6.38.8-32 - ath5k-disable-fast-channel-switching-by-default.patch (rhbz#709122) (korgbz#34992) [a99168ee in wireless-next] From aa53a627e56250a52363abd44571e890547d7718 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 15 Jun 2011 10:17:02 -0400 Subject: [PATCH 76/99] crypto: aesni-intel - Merge with fpu.ko --- crypto-aesni_intel-merge-with-fpu_ko.patch | 134 +++++++++++++++++++++ kernel.spec | 8 ++ 2 files changed, 142 insertions(+) create mode 100644 crypto-aesni_intel-merge-with-fpu_ko.patch diff --git a/crypto-aesni_intel-merge-with-fpu_ko.patch b/crypto-aesni_intel-merge-with-fpu_ko.patch new file mode 100644 index 000000000..afb4bec8b --- /dev/null +++ b/crypto-aesni_intel-merge-with-fpu_ko.patch @@ -0,0 +1,134 @@ +From: Andy Lutomirski +Date: Mon, 16 May 2011 05:12:47 +0000 (+1000) +Subject: crypto: aesni-intel - Merge with fpu.ko +X-Git-Tag: v3.0-rc1~371^2~5 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=b23b64516500df6b70fcafb820970f18538252cf + +crypto: aesni-intel - Merge with fpu.ko + +Loading fpu without aesni-intel does nothing. Loading aesni-intel +without fpu causes modes like xts to fail. (Unloading +aesni-intel will restore those modes.) + +One solution would be to make aesni-intel depend on fpu, but it +seems cleaner to just combine the modules. + +This is probably responsible for bugs like: +https://bugzilla.redhat.com/show_bug.cgi?id=589390 + +Signed-off-by: Andy Lutomirski +Signed-off-by: Herbert Xu +[also 9bed4aca for the bugfix. --kyle] + +--- +diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile +index 1a58ad8..c04f1b7 100644 +--- a/arch/x86/crypto/Makefile ++++ b/arch/x86/crypto/Makefile +@@ -2,8 +2,6 @@ + # Arch-specific CryptoAPI modules. + # + +-obj-$(CONFIG_CRYPTO_FPU) += fpu.o +- + obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o + obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o + obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o +@@ -24,6 +22,6 @@ aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o + twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o + salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o + +-aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o ++aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o + + ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o +diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c +index b375b2a..ede3fa7 100644 +--- a/arch/x86/crypto/aesni-intel_glue.c ++++ b/arch/x86/crypto/aesni-intel_glue.c +@@ -94,6 +94,10 @@ asmlinkage void aesni_cbc_enc(struct crypto_aes_ctx *ctx, u8 *out, + const u8 *in, unsigned int len, u8 *iv); + asmlinkage void aesni_cbc_dec(struct crypto_aes_ctx *ctx, u8 *out, + const u8 *in, unsigned int len, u8 *iv); ++ ++int crypto_fpu_init(void); ++void crypto_fpu_exit(void); ++ + #ifdef CONFIG_X86_64 + asmlinkage void aesni_ctr_enc(struct crypto_aes_ctx *ctx, u8 *out, + const u8 *in, unsigned int len, u8 *iv); +@@ -1259,6 +1263,8 @@ static int __init aesni_init(void) + return -ENODEV; + } + ++ if ((err = crypto_fpu_init())) ++ goto fpu_err; + if ((err = crypto_register_alg(&aesni_alg))) + goto aes_err; + if ((err = crypto_register_alg(&__aesni_alg))) +@@ -1336,6 +1342,7 @@ blk_ecb_err: + __aes_err: + crypto_unregister_alg(&aesni_alg); + aes_err: ++fpu_err: + return err; + } + +@@ -1365,6 +1372,8 @@ static void __exit aesni_exit(void) + crypto_unregister_alg(&blk_ecb_alg); + crypto_unregister_alg(&__aesni_alg); + crypto_unregister_alg(&aesni_alg); ++ ++ crypto_fpu_exit(); + } + + module_init(aesni_init); +diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c +index 1a8f864..98d7a18 100644 +--- a/arch/x86/crypto/fpu.c ++++ b/arch/x86/crypto/fpu.c +@@ -150,18 +150,12 @@ static struct crypto_template crypto_fpu_tmpl = { + .module = THIS_MODULE, + }; + +-static int __init crypto_fpu_module_init(void) ++int __init crypto_fpu_init(void) + { + return crypto_register_template(&crypto_fpu_tmpl); + } + +-static void __exit crypto_fpu_module_exit(void) ++void __exit crypto_fpu_exit(void) + { + crypto_unregister_template(&crypto_fpu_tmpl); + } +- +-module_init(crypto_fpu_module_init); +-module_exit(crypto_fpu_module_exit); +- +-MODULE_LICENSE("GPL"); +-MODULE_DESCRIPTION("FPU block cipher wrapper"); +diff --git a/crypto/Kconfig b/crypto/Kconfig +index 4b7cb0e..87b22ca 100644 +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -264,11 +264,6 @@ config CRYPTO_XTS + key size 256, 384 or 512 bits. This implementation currently + can't handle a sectorsize which is not a multiple of 16 bytes. + +-config CRYPTO_FPU +- tristate +- select CRYPTO_BLKCIPHER +- select CRYPTO_MANAGER +- + comment "Hash modes" + + config CRYPTO_HMAC +@@ -543,7 +538,6 @@ config CRYPTO_AES_NI_INTEL + select CRYPTO_AES_586 if !64BIT + select CRYPTO_CRYPTD + select CRYPTO_ALGAPI +- select CRYPTO_FPU + help + Use Intel AES-NI instructions for AES algorithm. + diff --git a/kernel.spec b/kernel.spec index 465a8bf7e..0b8e71609 100644 --- a/kernel.spec +++ b/kernel.spec @@ -751,6 +751,8 @@ Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch Patch12418: ath5k-disable-fast-channel-switching-by-default.patch +Patch12420: crypto-aesni_intel-merge-with-fpu_ko.patch + %endif BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root @@ -1395,6 +1397,9 @@ ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch # rhbz#709122 ApplyPatch ath5k-disable-fast-channel-switching-by-default.patch +# rhbz#589390 +ApplyPatch crypto-aesni_intel-merge-with-fpu_ko.patch + # END OF PATCH APPLICATIONS %endif @@ -2003,6 +2008,9 @@ fi # and build. %changelog +* Wed Jun 15 2011 Kyle McMartin +- crypto: aesni-intel - Merge with fpu.ko (rhbz#589390) + * Thu Jun 09 2011 Kyle McMartin 2.6.38.8-32 - ath5k-disable-fast-channel-switching-by-default.patch (rhbz#709122) (korgbz#34992) [a99168ee in wireless-next] From 622985637b49e11af7ae086eaa2138828772c0e1 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 20 Jun 2011 10:16:07 -0400 Subject: [PATCH 77/99] [sgruszka@] iwlwifi: fix general 11n instability (rhbz#648732) --- ...f-protection-on-5000-adapters-series.patch | 103 ++++++++++++++++++ kernel.spec | 9 +- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch diff --git a/iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch b/iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch new file mode 100644 index 000000000..6743f9057 --- /dev/null +++ b/iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch @@ -0,0 +1,103 @@ +From sgruszka@redhat.com Mon Jun 20 10:09:55 2011 +From: Stanislaw Gruszka +To: kernel@lists.fedoraproject.org +Subject: [PATCH 2.6.38] iwlagn: use cts-to-self protection on 5000 adapters series +Date: Mon, 20 Jun 2011 16:11:22 +0200 +Message-Id: <1308579082-19006-2-git-send-email-sgruszka@redhat.com> + +This patch fixes 802.11n stability and performance regression we have +since 2.6.35. It boost performance on my 5GHz N-only network from about +5MB/s to 8MB/s. Similar percentage boost can be observed on 2.4 GHz. + +These are test results of 5x downloading of approximately 700MB iso +image: + +vanilla: 5.27 5.22 4.94 4.47 5.31 ; avr 5.0420 std 0.35110 +patched: 8.07 7.95 8.06 7.99 7.96 ; avr 8.0060 std 0.055946 + +This was achieved with NetworkManager configured to do not perform +periodical scans, by configuring constant BSSID. With periodical scans, +after some time, performance downgrade to unpatched driver level, like +in example below: + +patched: 7.40 7.61 4.28 4.37 4.80 avr 5.6920 std 1.6683 + +However patch still make better here, since similar test on unpatched +driver make link disconnects with below messages after some time: + +wlan1: authenticate with 00:23:69:35:d1:3f (try 1) +wlan1: authenticate with 00:23:69:35:d1:3f (try 2) +wlan1: authenticate with 00:23:69:35:d1:3f (try 3) +wlan1: authentication with 00:23:69:35:d1:3f timed out + +On 2.6.35 kernel patch helps against connection hangs with messages: + +iwlagn 0000:20:00.0: queue 10 stuck 3 time. Fw reload. +iwlagn 0000:20:00.0: On demand firmware reload +iwlagn 0000:20:00.0: Stopping AGG while state not ON or starting + +Signed-off-by: Stanislaw Gruszka +--- + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - + drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 12 ++---------- + drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 8 ++++++++ + 3 files changed, 10 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c +index 537fb8c..909cc30 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-5000.c ++++ b/drivers/net/wireless/iwlwifi/iwl-5000.c +@@ -517,7 +517,6 @@ static struct iwl_base_params iwl5000_base_params = { + }; + static struct iwl_ht_params iwl5000_ht_params = { + .ht_greenfield_support = true, +- .use_rts_for_aggregation = true, /* use rts/cts protection */ + }; + + #define IWL_DEVICE_5000 \ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +index 366340f..89762a7 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +@@ -217,17 +217,9 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, + __le16 fc, __le32 *tx_flags) + { + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || +- info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { ++ info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || ++ info->flags & IEEE80211_TX_CTL_AMPDU) + *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; +- return; +- } +- +- if (priv->cfg->ht_params && +- priv->cfg->ht_params->use_rts_for_aggregation && +- info->flags & IEEE80211_TX_CTL_AMPDU) { +- *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; +- return; +- } + } + + /* Calc max signal level (dBm) among 3 possible receivers */ +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +index ee802fe..b19fb85 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +@@ -145,6 +145,14 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) + /* always get timestamp with Rx frame */ + ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; + ++ /* ++ * force CTS-to-self frames protection if RTS-CTS is not preferred ++ * one aggregation protection method ++ */ ++ if (!(priv->cfg->ht_params && ++ priv->cfg->ht_params->use_rts_for_aggregation)) ++ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; ++ + if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || + !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) + ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; +-- +1.7.1 + diff --git a/kernel.spec b/kernel.spec index 0b8e71609..02301f0fc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 32 +%global baserelease 33 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -750,6 +750,7 @@ Patch12415: hid-multitouch-add-support-for-elo-touchsystems.patch Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch Patch12418: ath5k-disable-fast-channel-switching-by-default.patch +Patch12419: iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch Patch12420: crypto-aesni_intel-merge-with-fpu_ko.patch @@ -1397,6 +1398,9 @@ ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch # rhbz#709122 ApplyPatch ath5k-disable-fast-channel-switching-by-default.patch +# rhbz#648732 +ApplyPatch iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch + # rhbz#589390 ApplyPatch crypto-aesni_intel-merge-with-fpu_ko.patch @@ -2008,6 +2012,9 @@ fi # and build. %changelog +* Mon Jun 20 2011 Kyle McMartin 2.6.38.8-33 +- [sgruszka@] iwlwifi: fix general 11n instability (rhbz#648732) + * Wed Jun 15 2011 Kyle McMartin - crypto: aesni-intel - Merge with fpu.ko (rhbz#589390) From 7bbc91a67d83cdead4f616bf6d3020b656a40729 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 21 Jun 2011 16:06:15 -0400 Subject: [PATCH 78/99] HID: ntrig don't dereference unclaimed hidinput (rhbz#714827) --- hid-ntrig-deref-unclaimed-input.patch | 46 +++++++++++++++++++++++++++ kernel.spec | 8 +++++ 2 files changed, 54 insertions(+) create mode 100644 hid-ntrig-deref-unclaimed-input.patch diff --git a/hid-ntrig-deref-unclaimed-input.patch b/hid-ntrig-deref-unclaimed-input.patch new file mode 100644 index 000000000..8719eae30 --- /dev/null +++ b/hid-ntrig-deref-unclaimed-input.patch @@ -0,0 +1,46 @@ +commit f41a52d3010579949a3b9fd76783120d9643b60b +Author: Rafi Rubin +Date: Tue Mar 8 00:24:29 2011 -0500 + + HID: ntrig don't dereference unclaimed hidinput + + Check before dereferencing field->hidinput to fix a reported invalid + deference bug. + + Signed-off-by: Rafi Rubin + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c +index beb4034..a93e58c 100644 +--- a/drivers/hid/hid-ntrig.c ++++ b/drivers/hid/hid-ntrig.c +@@ -539,8 +539,19 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, + static int ntrig_event (struct hid_device *hid, struct hid_field *field, + struct hid_usage *usage, __s32 value) + { +- struct input_dev *input = field->hidinput->input; + struct ntrig_data *nd = hid_get_drvdata(hid); ++ struct input_dev *input; ++ ++ /* Skip processing if not a claimed input */ ++ if (!(hid->claimed & HID_CLAIMED_INPUT)) ++ goto not_claimed_input; ++ ++ /* This function is being called before the structures are fully ++ * initialized */ ++ if(!(field->hidinput && field->hidinput->input)) ++ return -EINVAL; ++ ++ input = field->hidinput->input; + + /* No special handling needed for the pen */ + if (field->application == HID_DG_PEN) +@@ -810,6 +821,8 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, + } + } + ++not_claimed_input: ++ + /* we have handled the hidinput part, now remains hiddev */ + if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) + hid->hiddev_hid_event(hid, field, usage, value); diff --git a/kernel.spec b/kernel.spec index 02301f0fc..c5127878e 100644 --- a/kernel.spec +++ b/kernel.spec @@ -746,9 +746,12 @@ Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patc Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch +Patch12410: hid-ntrig-deref-unclaimed-input.patch + Patch12415: hid-multitouch-add-support-for-elo-touchsystems.patch Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch + Patch12418: ath5k-disable-fast-channel-switching-by-default.patch Patch12419: iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch @@ -1392,6 +1395,8 @@ ApplyPatch bonding-incorrect-tx-queue-offset.patch ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch +ApplyPatch hid-ntrig-deref-unclaimed-input.patch + ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch @@ -2012,6 +2017,9 @@ fi # and build. %changelog +* Tue Jun 21 2011 Dave Jones +- HID: ntrig don't dereference unclaimed hidinput (rhbz#714827) + * Mon Jun 20 2011 Kyle McMartin 2.6.38.8-33 - [sgruszka@] iwlwifi: fix general 11n instability (rhbz#648732) From 9a9eea350247aab4b360014409b4fad106a69585 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 23 Jun 2011 23:10:02 -0400 Subject: [PATCH 79/99] drm-radeon-update3.patch: more radeon fixes backport --- drm-radeon-update3.patch | 820 +++++++++++++++++++++++++++++++++++++++ kernel.spec | 5 + 2 files changed, 825 insertions(+) create mode 100644 drm-radeon-update3.patch diff --git a/drm-radeon-update3.patch b/drm-radeon-update3.patch new file mode 100644 index 000000000..626ccdc4b --- /dev/null +++ b/drm-radeon-update3.patch @@ -0,0 +1,820 @@ +commit 3c79cf677a2eca93762d15f69744937d43185573 +Author: Alex Deucher +Date: Thu Jun 23 12:19:32 2011 -0400 + + drm/radeon/kms: handle special cases for vddc + + A voltage value of 0xff01 requires that the driver + look up the max voltage for the board based using the + atom SetVoltage command table. + + Setting the proper voltage should fix stability on + some newer asics. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 63311583922e52b7687233c18e9eebe83207d2e8 +Author: Alex Deucher +Date: Thu Jun 23 00:49:29 2011 -0400 + + drm/radeon/kms: fix num_banks tiling config for fusion + + The field is encoded: + 0 = 4 banks + 1 = 8 banks + 2 = 16 banks + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 1421991c155016ce31777d09ebfdfe3eb04cb78c +Author: Alex Deucher +Date: Mon Jun 20 13:00:31 2011 -0400 + + drm/radeon/kms/r6xx+: voltage fixes + + 0xff01 is not an actual voltage value, but a flag + for the driver. If the power state as that value, + skip setting the voltage. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit a7b65dda144af8ba443f1745875440c87a41b0a3 +Author: Dave Airlie +Date: Sat Jun 18 03:59:51 2011 +0000 + + drm/radeon: avoid warnings from r600/eg irq handlers on powered off card. + + Since we were calling the wptr function before checking if the IH was + even enabled, or the GPU wasn't shutdown, we'd get spam in the logs when + the GPU readback 0xffffffff. This reorders things so we return early + in the no IH and GPU shutdown cases. + + Reported-and-tested-by: ManDay on #radeon + Reviewed-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 3f662051e0acf55bc8c2ea246c9f05e004a2d698 +Author: Alex Deucher +Date: Fri Jun 17 06:11:30 2011 +0000 + + drm/radeon/kms: add missing param for dce3.2 DP transmitter setup + + This is used during phy init to set up the phy for DP. This may + fix DP problems on DCE3.2 cards. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit dc4f34ba0796f4b09501b035825c02c405335063 +Author: Alex Deucher +Date: Fri Jun 17 13:13:52 2011 -0400 + + drm/radeon/kms/atom: fix duallink on some early DCE3.2 cards + + Certain revisions of the vbios on DCE3.2 cards have a bug + in the transmitter control table which prevents duallink from + being enabled properly on some cards. The action switch statement + jumps to the wrong offset for the OUTPUT_ENABLE action. The fix + is to use the ENABLE action rather than the OUTPUT_ENABLE action + on the affected cards. In fixed version of the vbios, both + actions jump to the same offset, so the change should be safe. + + Reported-and-tested-by: Dave Airlie + Signed-off-by: Alex Deucher + Cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit b5097472f2119480f60657f92b17dd79bcf8e24a +Author: Alex Deucher +Date: Mon Jun 13 17:39:06 2011 -0400 + + drm/radeon/kms: use helper functions for fence read/write + + The existing code assumed scratch registers in a number + of places while in most cases we are be using writeback + and events rather than scratch registers. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 4414ac4ea84407d14e9fde512c1c229f9cfc96c4 +Author: Alex Deucher +Date: Thu Jun 16 18:14:22 2011 +0000 + + drm/radeon/kms: fix num crtcs for Cedar and Caicos + + Only support 4 rather than 6. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit c4eee24a87a71c14f223e85065cccea6bf32321d +Author: Alex Deucher +Date: Mon Jun 13 22:02:51 2011 +0000 + + drm/radeon/kms: clear wb memory by default + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit 12ca85df2db5988ea5c53d0ee53ff1b1cf1257fd +Author: Alex Deucher +Date: Tue Jun 14 19:15:53 2011 +0000 + + drm/radeon/kms: signed fix for evergreen thermal + + temperature is signed. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit dd53acd144d8fa6385e50949f4f635890420ba0b +Author: Alex Deucher +Date: Wed Jun 8 13:01:11 2011 -0400 + + drm/radeon/kms: check modes against max pixel clock + + Filter out modes that are higher than the max pixel + clock. + + Signed-off-by: Alex Deucher + Signed-off-by: Dave Airlie + +commit a812b560d0d041f2318ae4243ead692e26bae429 +Author: Daniel Haid +Date: Wed Jun 8 20:04:45 2011 +1000 + + drm/radeon/kms: fix for radeon on systems >4GB without hardware iommu + + On my x86_64 system with >4GB of ram and swiotlb instead of + a hardware iommu (because I have a VIA chipset), the call + to pci_set_dma_mask (see below) with 40bits returns an error. + + But it seems that the radeon driver is designed to have + need_dma32 = true exactly if pci_set_dma_mask is called + with 32 bits and false if it is called with 40 bits. + + I have read somewhere that the default are 32 bits. So if the + call fails I suppose that need_dma32 should be set to true. + + And indeed the patch fixes the problem I have had before + and which I had described here: + http://choon.net/forum/read.php?21,106131,115940 + + Acked-by: Alex Deucher + cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 262016fe924bbc06d50bcfc816c635d465cd503d +Author: Alex Deucher +Date: Fri May 27 10:05:03 2011 -0400 + + drm/radeon/kms: viewport height has to be even + + Otherwise, no vblank interrupts. + Fixes: + https://bugs.freedesktop.org/show_bug.cgi?id=37522 + + Signed-off-by: Alex Deucher + Cc: stable@kernel.org + Signed-off-by: Dave Airlie + +commit 36b3cb168810e68ae8dd2036189c4f2cfc0c6d49 +Author: Marek Olšák +Date: Fri Jun 10 14:41:26 2011 +0000 + + drm/radeon/kms: do bounds checking for 3D_LOAD_VBPNTR and bump array limit + + To my knowledge, the limit is 16 on r300. + (the docs don't say what the limit is) + + The lack of bounds checking can be abused to do all sorts of things + (from bypassing parts of the CS checker to crashing the kernel). + + Bugzilla: + https://bugs.freedesktop.org/show_bug.cgi?id=36745 + + Cc: stable@kernel.org + Signed-off-by: Marek Olšák + Signed-off-by: Dave Airlie +diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c +index 2bab32f..1fce6b7 100644 +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -1011,7 +1011,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + uint64_t fb_location; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); +- u32 tmp; ++ u32 tmp, viewport_w, viewport_h; + int r; + + /* no fb bound */ +@@ -1137,8 +1137,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, + y &= ~1; + WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, + (x << 16) | y); ++ viewport_w = crtc->mode.hdisplay; ++ viewport_h = (crtc->mode.vdisplay + 1) & ~1; + WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, +- (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); ++ (viewport_w << 16) | viewport_h); + + /* pageflip setup */ + /* make sure flip is at vb rather than hb */ +@@ -1179,7 +1181,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, + uint64_t fb_location; + uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; +- u32 tmp; ++ u32 tmp, viewport_w, viewport_h; + int r; + + /* no fb bound */ +@@ -1304,8 +1306,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, + y &= ~1; + WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, + (x << 16) | y); ++ viewport_w = crtc->mode.hdisplay; ++ viewport_h = (crtc->mode.vdisplay + 1) & ~1; + WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, +- (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); ++ (viewport_w << 16) | viewport_h); + + /* pageflip setup */ + /* make sure flip is at vb rather than hb */ +diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c +index 1b583f8..81f5211 100644 +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) + /* get temperature in millidegrees */ + int evergreen_get_temp(struct radeon_device *rdev) + { +- u32 temp, toffset, actual_temp = 0; ++ u32 temp, toffset; ++ int actual_temp = 0; + + if (rdev->family == CHIP_JUNIPER) { + toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> +@@ -139,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev) + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if (voltage->type == VOLTAGE_SW) { ++ /* 0xff01 is a flag rather then an actual voltage */ ++ if (voltage->voltage == 0xff01) ++ return; + if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { + radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; + DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); + } ++ /* 0xff01 is a flag rather then an actual voltage */ ++ if (voltage->vddci == 0xff01) ++ return; + if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { + radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); + rdev->pm.current_vddci = voltage->vddci; +@@ -1954,9 +1961,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev) + rdev->config.evergreen.tile_config |= (3 << 0); + break; + } +- /* num banks is 8 on all fusion asics */ ++ /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ + if (rdev->flags & RADEON_IS_IGP) +- rdev->config.evergreen.tile_config |= 8 << 4; ++ rdev->config.evergreen.tile_config |= 1 << 4; + else + rdev->config.evergreen.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; +@@ -2636,28 +2643,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) + + int evergreen_irq_process(struct radeon_device *rdev) + { +- u32 wptr = evergreen_get_ih_wptr(rdev); +- u32 rptr = rdev->ih.rptr; ++ u32 wptr; ++ u32 rptr; + u32 src_id, src_data; + u32 ring_index; + unsigned long flags; + bool queue_hotplug = false; + +- DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); +- if (!rdev->ih.enabled) ++ if (!rdev->ih.enabled || rdev->shutdown) + return IRQ_NONE; + +- spin_lock_irqsave(&rdev->ih.lock, flags); ++ wptr = evergreen_get_ih_wptr(rdev); ++ rptr = rdev->ih.rptr; ++ DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); + ++ spin_lock_irqsave(&rdev->ih.lock, flags); + if (rptr == wptr) { + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_NONE; + } +- if (rdev->shutdown) { +- spin_unlock_irqrestore(&rdev->ih.lock, flags); +- return IRQ_NONE; +- } +- + restart_ih: + /* display interrupts */ + evergreen_irq_ack(rdev); +diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h +index 2fef9de..686f9dc 100644 +--- a/drivers/gpu/drm/radeon/r100_track.h ++++ b/drivers/gpu/drm/radeon/r100_track.h +@@ -63,7 +63,7 @@ struct r100_cs_track { + unsigned num_arrays; + unsigned max_indx; + unsigned color_channel_mask; +- struct r100_cs_track_array arrays[11]; ++ struct r100_cs_track_array arrays[16]; + struct r100_cs_track_cb cb[R300_MAX_CB]; + struct r100_cs_track_cb zb; + struct r100_cs_track_cb aa; +@@ -146,6 +146,12 @@ static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, + ib = p->ib->ptr; + track = (struct r100_cs_track *)p->track; + c = radeon_get_ib_value(p, idx++) & 0x1F; ++ if (c > 16) { ++ DRM_ERROR("Only 16 vertex buffers are allowed %d\n", ++ pkt->opcode); ++ r100_cs_dump_packet(p, pkt); ++ return -EINVAL; ++ } + track->num_arrays = c; + for (i = 0; i < (c - 1); i+=2, idx+=3) { + r = r100_cs_packet_next_reloc(p, &reloc); +diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c +index 70e9fb0..e7157b7 100644 +--- a/drivers/gpu/drm/radeon/r600.c ++++ b/drivers/gpu/drm/radeon/r600.c +@@ -586,6 +586,9 @@ void r600_pm_misc(struct radeon_device *rdev) + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { ++ /* 0xff01 is a flag rather then an actual voltage */ ++ if (voltage->voltage == 0xff01) ++ return; + if (voltage->voltage != rdev->pm.current_vddc) { + radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; +@@ -3286,27 +3289,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) + + int r600_irq_process(struct radeon_device *rdev) + { +- u32 wptr = r600_get_ih_wptr(rdev); +- u32 rptr = rdev->ih.rptr; ++ u32 wptr; ++ u32 rptr; + u32 src_id, src_data; + u32 ring_index; + unsigned long flags; + bool queue_hotplug = false; + +- DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); +- if (!rdev->ih.enabled) ++ if (!rdev->ih.enabled || rdev->shutdown) + return IRQ_NONE; + ++ wptr = r600_get_ih_wptr(rdev); ++ rptr = rdev->ih.rptr; ++ DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); ++ + spin_lock_irqsave(&rdev->ih.lock, flags); + + if (rptr == wptr) { + spin_unlock_irqrestore(&rdev->ih.lock, flags); + return IRQ_NONE; + } +- if (rdev->shutdown) { +- spin_unlock_irqrestore(&rdev->ih.lock, flags); +- return IRQ_NONE; +- } + + restart_ih: + /* display interrupts */ +diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h +index 27df931..c46552d 100644 +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -165,6 +165,7 @@ struct radeon_clock { + uint32_t default_sclk; + uint32_t default_dispclk; + uint32_t dp_extclk; ++ uint32_t max_pixel_clock; + }; + + /* +@@ -178,6 +179,7 @@ void radeon_pm_resume(struct radeon_device *rdev); + void radeon_combios_get_power_modes(struct radeon_device *rdev); + void radeon_atombios_get_power_modes(struct radeon_device *rdev); + void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); ++int radeon_atom_get_max_vddc(struct radeon_device *rdev, u16 *voltage); + void rs690_pm_info(struct radeon_device *rdev); + extern int rv6xx_get_temp(struct radeon_device *rdev); + extern int rv770_get_temp(struct radeon_device *rdev); +diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c +index b9b3c2a..6f5bd29 100644 +--- a/drivers/gpu/drm/radeon/radeon_asic.c ++++ b/drivers/gpu/drm/radeon/radeon_asic.c +@@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = { + int radeon_asic_init(struct radeon_device *rdev) + { + radeon_register_accessor_init(rdev); ++ ++ /* set the number of crtcs */ ++ if (rdev->flags & RADEON_SINGLE_CRTC) ++ rdev->num_crtc = 1; ++ else ++ rdev->num_crtc = 2; ++ + switch (rdev->family) { + case CHIP_R100: + case CHIP_RV100: +@@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev) + case CHIP_JUNIPER: + case CHIP_CYPRESS: + case CHIP_HEMLOCK: ++ /* set num crtcs */ ++ if (rdev->family == CHIP_CEDAR) ++ rdev->num_crtc = 4; ++ else ++ rdev->num_crtc = 6; + rdev->asic = &evergreen_asic; + break; + case CHIP_PALM: +@@ -1025,10 +1037,17 @@ int radeon_asic_init(struct radeon_device *rdev) + case CHIP_BARTS: + case CHIP_TURKS: + case CHIP_CAICOS: ++ /* set num crtcs */ ++ if (rdev->family == CHIP_CAICOS) ++ rdev->num_crtc = 4; ++ else ++ rdev->num_crtc = 6; + rdev->asic = &btc_asic; + break; + case CHIP_CAYMAN: + rdev->asic = &cayman_asic; ++ /* set num crtcs */ ++ rdev->num_crtc = 6; + break; + default: + /* FIXME: not supported yet */ +@@ -1040,18 +1059,6 @@ int radeon_asic_init(struct radeon_device *rdev) + rdev->asic->set_memory_clock = NULL; + } + +- /* set the number of crtcs */ +- if (rdev->flags & RADEON_SINGLE_CRTC) +- rdev->num_crtc = 1; +- else { +- if (ASIC_IS_DCE41(rdev)) +- rdev->num_crtc = 2; +- else if (ASIC_IS_DCE4(rdev)) +- rdev->num_crtc = 6; +- else +- rdev->num_crtc = 2; +- } +- + return 0; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c +index f116516..ce861ff 100644 +--- a/drivers/gpu/drm/radeon/radeon_atombios.c ++++ b/drivers/gpu/drm/radeon/radeon_atombios.c +@@ -1246,6 +1246,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) + } + *dcpll = *p1pll; + ++ rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock); ++ if (rdev->clock.max_pixel_clock == 0) ++ rdev->clock.max_pixel_clock = 40000; ++ + return true; + } + +@@ -2308,6 +2312,14 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, + le16_to_cpu(clock_info->r600.usVDDC); + } + ++ /* patch up vddc if necessary */ ++ if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) { ++ u16 vddc; ++ ++ if (radeon_atom_get_max_vddc(rdev, &vddc) == 0) ++ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; ++ } ++ + if (rdev->flags & RADEON_IS_IGP) { + /* skip invalid modes */ + if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) +@@ -2595,6 +2607,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return; + ++ /* 0xff01 is a flag rather then an actual voltage */ ++ if (voltage_level == 0xff01) ++ return; ++ + switch (crev) { + case 1: + args.v1.ucVoltageType = voltage_type; +@@ -2614,7 +2630,35 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + } + ++int radeon_atom_get_max_vddc(struct radeon_device *rdev, ++ u16 *voltage) ++{ ++ union set_voltage args; ++ int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); ++ u8 frev, crev; ++ ++ if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) ++ return -EINVAL; + ++ switch (crev) { ++ case 1: ++ return -EINVAL; ++ case 2: ++ args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; ++ args.v2.ucVoltageMode = 0; ++ args.v2.usVoltageLevel = 0; ++ ++ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); ++ ++ *voltage = le16_to_cpu(args.v2.usVoltageLevel); ++ break; ++ default: ++ DRM_ERROR("Unknown table version %d, %d\n", frev, crev); ++ return -EINVAL; ++ } ++ ++ return 0; ++} + + void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) + { +diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c +index 5249af8..2d48e7a 100644 +--- a/drivers/gpu/drm/radeon/radeon_clocks.c ++++ b/drivers/gpu/drm/radeon/radeon_clocks.c +@@ -117,7 +117,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) + p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; + if (p1pll->reference_div < 2) + p1pll->reference_div = 12; +- p2pll->reference_div = p1pll->reference_div; ++ p2pll->reference_div = p1pll->reference_div; + + /* These aren't in the device-tree */ + if (rdev->family >= CHIP_R420) { +@@ -139,6 +139,8 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) + p2pll->pll_out_min = 12500; + p2pll->pll_out_max = 35000; + } ++ /* not sure what the max should be in all cases */ ++ rdev->clock.max_pixel_clock = 35000; + + spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; + spll->reference_div = mpll->reference_div = +@@ -151,7 +153,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) + else + rdev->clock.default_sclk = + radeon_legacy_get_engine_clock(rdev); +- ++ + val = of_get_property(dp, "ATY,MCLK", NULL); + if (val && *val) + rdev->clock.default_mclk = (*val) / 10; +@@ -160,7 +162,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) + radeon_legacy_get_memory_clock(rdev); + + DRM_INFO("Using device-tree clock info\n"); +- ++ + return true; + } + #else +diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c +index 089ab92..8a53691 100644 +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -833,6 +833,11 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) + rdev->clock.default_sclk = sclk; + rdev->clock.default_mclk = mclk; + ++ if (RBIOS32(pll_info + 0x16)) ++ rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16); ++ else ++ rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */ ++ + return true; + } + return false; +diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c +index a186673..33cb72b 100644 +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -621,8 +621,14 @@ static int radeon_vga_get_modes(struct drm_connector *connector) + static int radeon_vga_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) + { ++ struct drm_device *dev = connector->dev; ++ struct radeon_device *rdev = dev->dev_private; ++ + /* XXX check mode bandwidth */ +- /* XXX verify against max DAC output frequency */ ++ ++ if ((mode->clock / 10) > rdev->clock.max_pixel_clock) ++ return MODE_CLOCK_HIGH; ++ + return MODE_OK; + } + +@@ -1010,6 +1016,11 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, + } else + return MODE_CLOCK_HIGH; + } ++ ++ /* check against the max pixel clock */ ++ if ((mode->clock / 10) > rdev->clock.max_pixel_clock) ++ return MODE_CLOCK_HIGH; ++ + return MODE_OK; + } + +diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c +index 207d43f..8a64a3b 100644 +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -213,6 +213,8 @@ int radeon_wb_init(struct radeon_device *rdev) + return r; + } + ++ /* clear wb memory */ ++ memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE); + /* disable event_write fences */ + rdev->wb.use_event = false; + /* disabled via module param */ +@@ -752,6 +754,7 @@ int radeon_device_init(struct radeon_device *rdev, + dma_bits = rdev->need_dma32 ? 32 : 40; + r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { ++ rdev->need_dma32 = true; + printk(KERN_WARNING "radeon: No suitable DMA available.\n"); + } + +diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c +index b427488..e2a1c7d 100644 +--- a/drivers/gpu/drm/radeon/radeon_encoders.c ++++ b/drivers/gpu/drm/radeon/radeon_encoders.c +@@ -994,9 +994,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t + break; + } + +- if (is_dp) ++ if (is_dp) { + args.v2.acConfig.fCoherentMode = 1; +- else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { ++ args.v2.acConfig.fDPConnector = 1; ++ } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { + if (dig->coherent_mode) + args.v2.acConfig.fCoherentMode = 1; + if (radeon_encoder->pixel_clock > 165000) +@@ -1294,7 +1295,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) + if (is_dig) { + switch (mode) { + case DRM_MODE_DPMS_ON: +- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); ++ /* some early dce3.2 boards have a bug in their transmitter control table */ ++ if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) ++ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); ++ else ++ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + +diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c +index 2b0ee62..3285de1 100644 +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -40,6 +40,35 @@ + #include "radeon.h" + #include "radeon_trace.h" + ++static void radeon_fence_write(struct radeon_device *rdev, u32 seq) ++{ ++ if (rdev->wb.enabled) { ++ u32 scratch_index; ++ if (rdev->wb.use_event) ++ scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; ++ else ++ scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; ++ rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);; ++ } else ++ WREG32(rdev->fence_drv.scratch_reg, seq); ++} ++ ++static u32 radeon_fence_read(struct radeon_device *rdev) ++{ ++ u32 seq; ++ ++ if (rdev->wb.enabled) { ++ u32 scratch_index; ++ if (rdev->wb.use_event) ++ scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; ++ else ++ scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; ++ seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); ++ } else ++ seq = RREG32(rdev->fence_drv.scratch_reg); ++ return seq; ++} ++ + int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) + { + unsigned long irq_flags; +@@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) + return 0; + } + fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); +- if (!rdev->cp.ready) { ++ if (!rdev->cp.ready) + /* FIXME: cp is not running assume everythings is done right + * away + */ +- WREG32(rdev->fence_drv.scratch_reg, fence->seq); +- } else ++ radeon_fence_write(rdev, fence->seq); ++ else + radeon_fence_ring_emit(rdev, fence); + + trace_radeon_fence_emit(rdev->ddev, fence->seq); +@@ -74,15 +103,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) + bool wake = false; + unsigned long cjiffies; + +- if (rdev->wb.enabled) { +- u32 scratch_index; +- if (rdev->wb.use_event) +- scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +- else +- scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +- seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); +- } else +- seq = RREG32(rdev->fence_drv.scratch_reg); ++ seq = radeon_fence_read(rdev); + if (seq != rdev->fence_drv.last_seq) { + rdev->fence_drv.last_seq = seq; + rdev->fence_drv.last_jiffies = jiffies; +@@ -253,7 +274,7 @@ retry: + r = radeon_gpu_reset(rdev); + if (r) + return r; +- WREG32(rdev->fence_drv.scratch_reg, fence->seq); ++ radeon_fence_write(rdev, fence->seq); + rdev->gpu_lockup = false; + } + timeout = RADEON_FENCE_JIFFIES_TIMEOUT; +@@ -353,7 +374,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev) + write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); + return r; + } +- WREG32(rdev->fence_drv.scratch_reg, 0); ++ radeon_fence_write(rdev, 0); + atomic_set(&rdev->fence_drv.seq, 0); + INIT_LIST_HEAD(&rdev->fence_drv.created); + INIT_LIST_HEAD(&rdev->fence_drv.emited); +@@ -393,7 +414,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) + struct radeon_fence *fence; + + seq_printf(m, "Last signaled fence 0x%08X\n", +- RREG32(rdev->fence_drv.scratch_reg)); ++ radeon_fence_read(rdev)); + if (!list_empty(&rdev->fence_drv.emited)) { + fence = list_entry(rdev->fence_drv.emited.prev, + struct radeon_fence, list); +diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c +index 114e5cc..cd9578b 100644 +--- a/drivers/gpu/drm/radeon/rv770.c ++++ b/drivers/gpu/drm/radeon/rv770.c +@@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev) + struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; + + if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { ++ /* 0xff01 is a flag rather then an actual voltage */ ++ if (voltage->voltage == 0xff01) ++ return; + if (voltage->voltage != rdev->pm.current_vddc) { + radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); + rdev->pm.current_vddc = voltage->voltage; diff --git a/kernel.spec b/kernel.spec index c5127878e..17ef97758 100644 --- a/kernel.spec +++ b/kernel.spec @@ -690,6 +690,7 @@ Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.pa Patch1840: drm-radeon-update.patch Patch1841: drm-radeon-update2.patch Patch1842: drm-radeon-pageflip-oops-fix.patch +Patch1843: drm-radeon-update3.patch Patch1900: linux-2.6-intel-iommu-igfx.patch @@ -1346,6 +1347,7 @@ ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.pa ApplyPatch drm-radeon-update.patch ApplyPatch drm-radeon-update2.patch ApplyPatch drm-radeon-pageflip-oops-fix.patch +ApplyPatch drm-radeon-update3.patch # linux1394 git patches #ApplyPatch linux-2.6-firewire-git-update.patch @@ -2017,6 +2019,9 @@ fi # and build. %changelog +* Thu Jun 23 2011 Dave Airlie +- drm-radeon-update3.patch: more radeon fixes backport + * Tue Jun 21 2011 Dave Jones - HID: ntrig don't dereference unclaimed hidinput (rhbz#714827) From bc6617c233dbb5a112ec0b41ec394517ea2efb82 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 23 Jun 2011 23:13:47 -0400 Subject: [PATCH 80/99] drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls --- drm-i915-snb-irq-stalls-fix.patch | 53 +++++++++++++++++++++++++++++++ kernel.spec | 5 +++ 2 files changed, 58 insertions(+) create mode 100644 drm-i915-snb-irq-stalls-fix.patch diff --git a/drm-i915-snb-irq-stalls-fix.patch b/drm-i915-snb-irq-stalls-fix.patch new file mode 100644 index 000000000..acf64da47 --- /dev/null +++ b/drm-i915-snb-irq-stalls-fix.patch @@ -0,0 +1,53 @@ +commit 498e720b96379d8ee9c294950a01534a73defcf3 +Author: Daniel J Blueman +Date: Fri Jun 17 11:32:19 2011 -0700 + + drm/i915: Fix gen6 (SNB) missed BLT ring interrupts. + + The failure appeared in dmesg as: + + [drm:i915_hangcheck_ring_idle] *ERROR* Hangcheck timer elapsed... blt + ring idle [waiting on 35064155, at 35064155], missed IRQ? + + This works around that problem on by making the blitter command + streamer write interrupt state to the Hardware Status Page when a + MI_USER_INTERRUPT command is decoded, which appears to force the seqno + out to memory before the interrupt happens. + + v1->v2: Moved to prior interrupt handler installation and RMW flags as + per feedback. + v2->v3: Removed RMW of flags (by anholt) + + Cc: stable@kernel.org + Signed-off-by: Daniel J Blueman + Signed-off-by: Eric Anholt + Tested-by: Chris Wilson [v1] + Tested-by: Eric Anholt [v1,v3] + (incidence of the bug with a testcase went from avg 2/1000 to + 0/12651 in the latest test run (plus more for v1)) + Tested-by: Kenneth Graunke [v1] + Tested-by: Robert Hooker [v1] + Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=33394 + Signed-off-by: Dave Airlie + +diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c +index b9fafe3..9e34a1a 100644 +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -1740,6 +1740,16 @@ void ironlake_irq_preinstall(struct drm_device *dev) + INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); + + I915_WRITE(HWSTAM, 0xeffe); ++ if (IS_GEN6(dev)) { ++ /* Workaround stalls observed on Sandy Bridge GPUs by ++ * making the blitter command streamer generate a ++ * write to the Hardware Status Page for ++ * MI_USER_INTERRUPT. This appears to serialize the ++ * previous seqno write out before the interrupt ++ * happens. ++ */ ++ I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); ++ } + + /* XXX hotplug from PCH */ + diff --git a/kernel.spec b/kernel.spec index 17ef97758..800765452 100644 --- a/kernel.spec +++ b/kernel.spec @@ -685,6 +685,7 @@ Patch1825: drm-intel-make-lvds-work.patch Patch1826: drm-intel-edp-fixes.patch Patch1828: drm-intel-eeebox-eb1007-quirk.patch Patch1829: drm-intel-restore-mode.patch +Patch1830: drm-i915-snb-irq-stalls-fix.patch # radeon - new hw + fixes for fusion and t500 regression Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch Patch1840: drm-radeon-update.patch @@ -1341,6 +1342,7 @@ ApplyPatch drm-intel-edp-fixes.patch ApplyPatch drm-i915-fix-pipelined-fencing.patch ApplyPatch drm-intel-eeebox-eb1007-quirk.patch ApplyPatch drm-intel-restore-mode.patch +ApplyPatch drm-i915-snb-irq-stalls-fix.patch # radeon DRM (add cayman support) ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -R @@ -2019,6 +2021,9 @@ fi # and build. %changelog +* Thu Jun 23 2011 Dave Airlie +- drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls + * Thu Jun 23 2011 Dave Airlie - drm-radeon-update3.patch: more radeon fixes backport From 797a5eb6193aefd214e4bf739f074ce0297dd844 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 23 Jun 2011 23:15:11 -0400 Subject: [PATCH 81/99] bump release for build --- kernel.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel.spec b/kernel.spec index 800765452..7b4325638 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,7 +51,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 33 +%global baserelease 34 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2021,7 +2021,7 @@ fi # and build. %changelog -* Thu Jun 23 2011 Dave Airlie +* Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls * Thu Jun 23 2011 Dave Airlie From ce8c06713657669302eb56d5751124d8709f18fc Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 24 Jun 2011 00:37:15 -0400 Subject: [PATCH 82/99] Minor cleanup: use upstream patch to export block_{get,put}_queue --- block-export-blk_-get-put-_queue.patch | 39 ++++++++++++++++++++++++++ block-queue-refcount.patch | 18 ------------ kernel.spec | 5 ++++ 3 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 block-export-blk_-get-put-_queue.patch diff --git a/block-export-blk_-get-put-_queue.patch b/block-export-blk_-get-put-_queue.patch new file mode 100644 index 000000000..05db7bd20 --- /dev/null +++ b/block-export-blk_-get-put-_queue.patch @@ -0,0 +1,39 @@ +From d86e0e83b32bc84600adb0b6ea1fce389b266682 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Fri, 27 May 2011 07:44:43 +0200 +Subject: block: export blk_{get,put}_queue() + +From: Jens Axboe + +commit d86e0e83b32bc84600adb0b6ea1fce389b266682 upstream. +[ backport to 2.6.38 ] + +We need them in SCSI to fix a bug, but currently they are not +exported to modules. Export them. + +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Chuck Ebbert + +--- + block/blk-core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -345,6 +345,7 @@ void blk_put_queue(struct request_queue + { + kobject_put(&q->kobj); + } ++EXPORT_SYMBOL(blk_put_queue); + + void blk_cleanup_queue(struct request_queue *q) + { +@@ -566,6 +567,7 @@ int blk_get_queue(struct request_queue * + + return 1; + } ++EXPORT_SYMBOL(blk_get_queue); + + static inline void blk_free_request(struct request_queue *q, struct request *rq) + { diff --git a/block-queue-refcount.patch b/block-queue-refcount.patch index c0f09a45a..d53dd1bac 100644 --- a/block-queue-refcount.patch +++ b/block-queue-refcount.patch @@ -41,21 +41,3 @@ index e639125..e0bd3f7 100644 /* NULL queue means the device can't be used */ sdev->request_queue = NULL; ---- linux-2.6.38.noarch/block/blk-core.c~ 2011-06-07 15:29:26.000000000 -0400 -+++ linux-2.6.38.noarch/block/blk-core.c 2011-06-07 15:29:49.000000000 -0400 -@@ -456,6 +456,7 @@ void blk_put_queue(struct request_queue - { - kobject_put(&q->kobj); - } -+EXPORT_SYMBOL(blk_put_queue); - - void blk_cleanup_queue(struct request_queue *q) - { -@@ -663,6 +664,7 @@ int blk_get_queue(struct request_queue * - - return 1; - } -+EXPORT_SYMBOL(blk_get_queue); - - static inline void blk_free_request(struct request_queue *q, struct request *rq) - { diff --git a/kernel.spec b/kernel.spec index 7b4325638..17efa77f6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -657,6 +657,7 @@ Patch570: linux-2.6-selinux-mprotect-checks.patch Patch580: linux-2.6-sparc-selinux-mprotect-checks.patch Patch600: block-queue-refcount.patch +Patch601: block-export-blk_-get-put-_queue.patch Patch610: hda_intel-prealloc-4mb-dmabuffer.patch @@ -1280,6 +1281,7 @@ ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch # SCSI Bits. # ApplyPatch block-queue-refcount.patch +ApplyPatch block-export-blk_-get-put-_queue.patch # ACPI @@ -2021,6 +2023,9 @@ fi # and build. %changelog +* Fri Jun 24 2011 Chuck Ebbert +- Minor cleanup: use upstream patch to export block_{get,put}_queue + * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls From 8744fb36cec05e68a9605a2c297e05f0111bf6c9 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 24 Jun 2011 00:44:32 -0400 Subject: [PATCH 83/99] fix potential oops introduced in 2.6.38.8 --- ...get-should-access-bd_disk-only-after.patch | 40 +++++++++++++++++++ kernel.spec | 6 ++- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 block-blkdev_get-should-access-bd_disk-only-after.patch diff --git a/block-blkdev_get-should-access-bd_disk-only-after.patch b/block-blkdev_get-should-access-bd_disk-only-after.patch new file mode 100644 index 000000000..956b04160 --- /dev/null +++ b/block-blkdev_get-should-access-bd_disk-only-after.patch @@ -0,0 +1,40 @@ +From 4c49ff3fe128ca68dabd07537415c419ad7f82f9 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 1 Jun 2011 08:27:41 +0200 +Subject: block: blkdev_get() should access ->bd_disk only after + success + +From: Tejun Heo + +commit 4c49ff3fe128ca68dabd07537415c419ad7f82f9 upstream. + +d4dc210f69 (block: don't block events on excl write for non-optical +devices) added dereferencing of bdev->bd_disk to test +GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; however, bdev->bd_disk can be +%NULL if open failed which can lead to an oops. + +Test the flag after testing open was successful, not before. + +Signed-off-by: Tejun Heo +Reported-by: David Miller +Tested-by: David Miller +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + fs/block_dev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -1272,8 +1272,8 @@ int blkdev_get(struct block_device *bdev + * individual writeable reference is too fragile given the + * way @mode is used in blkdev_get/put(). + */ +- if ((disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE) && +- !res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) { ++ if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder && ++ (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) { + bdev->bd_write_holder = true; + disk_block_events(disk); + } diff --git a/kernel.spec b/kernel.spec index 17efa77f6..ea0c19e73 100644 --- a/kernel.spec +++ b/kernel.spec @@ -658,6 +658,7 @@ Patch580: linux-2.6-sparc-selinux-mprotect-checks.patch Patch600: block-queue-refcount.patch Patch601: block-export-blk_-get-put-_queue.patch +Patch602: block-blkdev_get-should-access-bd_disk-only-after.patch Patch610: hda_intel-prealloc-4mb-dmabuffer.patch @@ -1278,10 +1279,11 @@ ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch #ApplyPatch ima-allow-it-to-be-completely-disabled-and-default-off.patch # -# SCSI Bits. +# SCSI / block Bits. # ApplyPatch block-queue-refcount.patch ApplyPatch block-export-blk_-get-put-_queue.patch +ApplyPatch block-blkdev_get-should-access-bd_disk-only-after.patch # ACPI @@ -2025,6 +2027,8 @@ fi %changelog * Fri Jun 24 2011 Chuck Ebbert - Minor cleanup: use upstream patch to export block_{get,put}_queue +- block-blkdev_get-should-access-bd_disk-only-after.patch: + fix potential oops introduced in 2.6.38.8 * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls From 7562ee4726a9098b8f07d64aac525ce0e6a7d45a Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 24 Jun 2011 00:51:46 -0400 Subject: [PATCH 84/99] ahci-add-another-pci-id-for-marvell.patch (#705960) --- ahci-add-another-pci-id-for-marvell.patch | 32 +++++++++++++++++++++++ kernel.spec | 10 ++++++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 ahci-add-another-pci-id-for-marvell.patch diff --git a/ahci-add-another-pci-id-for-marvell.patch b/ahci-add-another-pci-id-for-marvell.patch new file mode 100644 index 000000000..e7ac983fa --- /dev/null +++ b/ahci-add-another-pci-id-for-marvell.patch @@ -0,0 +1,32 @@ +From: Tejun Heo +Date: Mon, 29 Nov 2010 14:57:14 +0000 (+0100) +Subject: ahci: add another PCI ID for marvell +X-Git-Tag: v2.6.39-rc1~490^2 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=50be5e3657cd2851a297dc0b3fd459f25829d29b + +ahci: add another PCI ID for marvell + +1b4b:91a3 seems to be another PCI ID for marvell ahci. Add it. +Reported and tested in the following thread. + + http://thread.gmane.org/gmane.linux.kernel/1068354 + +Signed-off-by: Tejun Heo +Reported-by: Borislav Petkov +Reported-by: Alessandro Tagliapietra +Signed-off-by: Jeff Garzik +--- + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 0c22ebd..e62f693 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -385,6 +385,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { + .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ + { PCI_DEVICE(0x1b4b, 0x9125), + .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ ++ { PCI_DEVICE(0x1b4b, 0x91a3), ++ .driver_data = board_ahci_yes_fbs }, + + /* Promise */ + { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ diff --git a/kernel.spec b/kernel.spec index ea0c19e73..e15ec2402 100644 --- a/kernel.spec +++ b/kernel.spec @@ -656,11 +656,15 @@ Patch530: linux-2.6-silence-fbcon-logo.patch Patch570: linux-2.6-selinux-mprotect-checks.patch Patch580: linux-2.6-sparc-selinux-mprotect-checks.patch +# scsi / block Patch600: block-queue-refcount.patch Patch601: block-export-blk_-get-put-_queue.patch Patch602: block-blkdev_get-should-access-bd_disk-only-after.patch -Patch610: hda_intel-prealloc-4mb-dmabuffer.patch +# libata +Patch620: ahci-add-another-pci-id-for-marvell.patch + +Patch650: hda_intel-prealloc-4mb-dmabuffer.patch Patch700: linux-2.6-e1000-ich9-montevina.patch @@ -1285,6 +1289,9 @@ ApplyPatch block-queue-refcount.patch ApplyPatch block-export-blk_-get-put-_queue.patch ApplyPatch block-blkdev_get-should-access-bd_disk-only-after.patch +# libata +ApplyPatch ahci-add-another-pci-id-for-marvell.patch + # ACPI # ALSA @@ -2029,6 +2036,7 @@ fi - Minor cleanup: use upstream patch to export block_{get,put}_queue - block-blkdev_get-should-access-bd_disk-only-after.patch: fix potential oops introduced in 2.6.38.8 +- ahci-add-another-pci-id-for-marvell.patch (#705960) * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls From ced86e1611c925a35187083210c890f8bf7c83e8 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 24 Jun 2011 06:12:52 -0400 Subject: [PATCH 85/99] CVE-2011-2183: ksm: race between ksmd and exiting task --- kernel.spec | 8 ++ ...reference-in-scan-get-next-rmap-item.patch | 82 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch diff --git a/kernel.spec b/kernel.spec index e15ec2402..cf0787975 100644 --- a/kernel.spec +++ b/kernel.spec @@ -619,6 +619,9 @@ Patch30: linux-2.6-tracehook.patch Patch31: linux-2.6-utrace.patch Patch32: linux-2.6-utrace-ptrace.patch +# CVE-2011-2183 +Patch80: ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch + Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch @@ -1210,6 +1213,10 @@ ApplyPatch linux-2.6-tracehook.patch ApplyPatch linux-2.6-utrace.patch ApplyPatch linux-2.6-utrace-ptrace.patch +# mm patches +# CVE-2011-2183 +ApplyPatch ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch + # Architecture patches # x86(-64) # Restore reliable stack backtraces, and hopefully @@ -2037,6 +2044,7 @@ fi - block-blkdev_get-should-access-bd_disk-only-after.patch: fix potential oops introduced in 2.6.38.8 - ahci-add-another-pci-id-for-marvell.patch (#705960) +- CVE-2011-2183: ksm: race between ksmd and exiting task * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls diff --git a/ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch b/ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch new file mode 100644 index 000000000..d67cdc748 --- /dev/null +++ b/ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch @@ -0,0 +1,82 @@ +From: Hugh Dickins +Date: Wed, 15 Jun 2011 22:08:58 +0000 (-0700) +Subject: ksm: fix NULL pointer dereference in scan_get_next_rmap_item() +X-Git-Tag: v3.0-rc4~44 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=2b472611a32a72f4a118c069c2d62a1a3f087afd + +ksm: fix NULL pointer dereference in scan_get_next_rmap_item() + +Andrea Righi reported a case where an exiting task can race against +ksmd::scan_get_next_rmap_item (http://lkml.org/lkml/2011/6/1/742) easily +triggering a NULL pointer dereference in ksmd. + +ksm_scan.mm_slot == &ksm_mm_head with only one registered mm + +CPU 1 (__ksm_exit) CPU 2 (scan_get_next_rmap_item) + list_empty() is false +lock slot == &ksm_mm_head +list_del(slot->mm_list) +(list now empty) +unlock + lock + slot = list_entry(slot->mm_list.next) + (list is empty, so slot is still ksm_mm_head) + unlock + slot->mm == NULL ... Oops + +Close this race by revalidating that the new slot is not simply the list +head again. + +Andrea's test case: + +#include +#include +#include +#include + +#define BUFSIZE getpagesize() + +int main(int argc, char **argv) +{ + void *ptr; + + if (posix_memalign(&ptr, getpagesize(), BUFSIZE) < 0) { + perror("posix_memalign"); + exit(1); + } + if (madvise(ptr, BUFSIZE, MADV_MERGEABLE) < 0) { + perror("madvise"); + exit(1); + } + *(char *)NULL = 0; + + return 0; +} + +Reported-by: Andrea Righi +Tested-by: Andrea Righi +Cc: Andrea Arcangeli +Signed-off-by: Hugh Dickins +Signed-off-by: Chris Wright +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + +diff --git a/mm/ksm.c b/mm/ksm.c +index d708b3e..9a68b0c 100644 +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -1302,6 +1302,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page) + slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list); + ksm_scan.mm_slot = slot; + spin_unlock(&ksm_mmlist_lock); ++ /* ++ * Although we tested list_empty() above, a racing __ksm_exit ++ * of the last mm on the list may have removed it since then. ++ */ ++ if (slot == &ksm_mm_head) ++ return NULL; + next_mm: + ksm_scan.address = 0; + ksm_scan.rmap_list = &slot->rmap_list; From 1412b6df72a6ad0c7c51310c119dcb28d5b80d78 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 24 Jun 2011 08:53:02 -0400 Subject: [PATCH 86/99] Revert 2.6.38.8 patch that broke magicmouse (#714381) --- ...ore-ivalid-report-id-while-switching.patch | 53 +++++++++++++++++++ kernel.spec | 8 ++- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 hid-magicmouse-ignore-ivalid-report-id-while-switching.patch diff --git a/hid-magicmouse-ignore-ivalid-report-id-while-switching.patch b/hid-magicmouse-ignore-ivalid-report-id-while-switching.patch new file mode 100644 index 000000000..db1b48360 --- /dev/null +++ b/hid-magicmouse-ignore-ivalid-report-id-while-switching.patch @@ -0,0 +1,53 @@ +From 23746a66d7d9e73402c68ef00d708796b97ebd72 Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Thu, 19 May 2011 17:58:07 +0200 +Subject: HID: magicmouse: ignore 'ivalid report id' while switching + modes + +From: Jiri Kosina + +commit 23746a66d7d9e73402c68ef00d708796b97ebd72 upstream. + +The device reponds with 'invalid report id' when feature report switching it +into multitouch mode is sent to it. + +This has been silently ignored before 0825411ade ("HID: bt: Wait for ACK +on Sent Reports"), but since this commit, it propagates -EIO from the _raw +callback . + +So let the driver ignore -EIO as response to 0xd7,0x01 report, as that's +how the device reacts in normal mode. + +Sad, but following reality. + +This fixes https://bugzilla.kernel.org/show_bug.cgi?id=35022 + +Tested-by: Chase Douglas +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-magicmouse.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -501,9 +501,17 @@ static int magicmouse_probe(struct hid_d + } + report->size = 6; + ++ /* ++ * The device reponds with 'invalid report id' when feature ++ * report switching it into multitouch mode is sent to it. ++ * ++ * This results in -EIO from the _raw low-level transport callback, ++ * but there seems to be no other way of switching the mode. ++ * Thus the super-ugly hacky success check below. ++ */ + ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), + HID_FEATURE_REPORT); +- if (ret != sizeof(feature)) { ++ if (ret != -EIO) { + hid_err(hdev, "unable to request touch data (%d)\n", ret); + goto err_stop_hw; + } diff --git a/kernel.spec b/kernel.spec index cf0787975..98d333076 100644 --- a/kernel.spec +++ b/kernel.spec @@ -649,6 +649,8 @@ Patch394: linux-2.6-acpi-debug-infinite-loop.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch +# revert 2.6.38.8 patch that broke magicmouse +Patch453: hid-magicmouse-ignore-ivalid-report-id-while-switching.patch Patch460: linux-2.6-serial-460800.patch @@ -1309,12 +1311,13 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # Misc fixes # The input layer spews crap no-one cares about. ApplyPatch linux-2.6-input-kill-stupid-messages.patch +ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch +# Revert 2.6.38.8 patch that broke magicmouse +ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching.patch -R # stop floppy.ko from autoloading during udev... ApplyPatch die-floppy-die.patch -ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch - # Allow to use 480600 baud on 16C950 UARTs ApplyPatch linux-2.6-serial-460800.patch @@ -2045,6 +2048,7 @@ fi fix potential oops introduced in 2.6.38.8 - ahci-add-another-pci-id-for-marvell.patch (#705960) - CVE-2011-2183: ksm: race between ksmd and exiting task +- Revert 2.6.38.8 patch that broke magicmouse (#714381) * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls From 1d95757421daf57e341d65fe2c8fbcc6b5ea064f Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 24 Jun 2011 15:25:26 -0400 Subject: [PATCH 87/99] Fix drive detection failure on mvsas (rhbz#705019) --- kernel.spec | 8 ++- ...t-frozen-flag-if-new-eh-is-supported.patch | 72 +++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch diff --git a/kernel.spec b/kernel.spec index 98d333076..80ee3ca15 100644 --- a/kernel.spec +++ b/kernel.spec @@ -668,6 +668,7 @@ Patch602: block-blkdev_get-should-access-bd_disk-only-after.patch # libata Patch620: ahci-add-another-pci-id-for-marvell.patch +Patch621: libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch Patch650: hda_intel-prealloc-4mb-dmabuffer.patch @@ -1300,6 +1301,8 @@ ApplyPatch block-blkdev_get-should-access-bd_disk-only-after.patch # libata ApplyPatch ahci-add-another-pci-id-for-marvell.patch +# Fix drive detection failure on mvsas (rhbz#705019) +ApplyPatch libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch # ACPI @@ -2046,9 +2049,10 @@ fi - Minor cleanup: use upstream patch to export block_{get,put}_queue - block-blkdev_get-should-access-bd_disk-only-after.patch: fix potential oops introduced in 2.6.38.8 -- ahci-add-another-pci-id-for-marvell.patch (#705960) +- ahci-add-another-pci-id-for-marvell.patch (rhbz#705960) - CVE-2011-2183: ksm: race between ksmd and exiting task -- Revert 2.6.38.8 patch that broke magicmouse (#714381) +- Revert 2.6.38.8 patch that broke magicmouse (rhbz#714381) +- Fix drive detection failure on mvsas (rhbz#705019) * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls diff --git a/libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch b/libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch new file mode 100644 index 000000000..85016b40a --- /dev/null +++ b/libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch @@ -0,0 +1,72 @@ +From: Nishanth Aravamudan +Date: Thu, 16 Jun 2011 15:28:36 +0000 (-0700) +Subject: libata/sas: only set FROZEN flag if new EH is supported +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=3f1e046ad3370d22d39529103667354eb50abc08 + +libata/sas: only set FROZEN flag if new EH is supported + +On 16.06.2011 [08:28:39 -0500], Brian King wrote: +> On 06/16/2011 02:51 AM, Tejun Heo wrote: +> > On Wed, Jun 15, 2011 at 04:34:17PM -0700, Nishanth Aravamudan wrote: +> >>> That looks like the right thing to do. For ipr's usage of +> >>> libata, we don't have the concept of a port frozen state, so this flag +> >>> should really never get set. The alternate way to fix this would be to +> >>> only set ATA_PFLAG_FROZEN in ata_port_alloc if ap->ops->error_handler +> >>> is not NULL. +> >> +> >> It seemed like ipr is as you say, but I wasn't sure if it was +> >> appropriate to make the change above in the common libata-scis code or +> >> not. I don't want to break some other device on accident. +> >> +> >> Also, I tried your suggestion, but I don't think that can happen in +> >> ata_port_alloc? ata_port_alloc is allocated ap itself, and it seems like +> >> ap->ops typically gets set only after ata_port_alloc returns? +> > +> > Maybe we can test error_handler in ata_sas_port_start()? +> +> Good point. Since libsas is converted to the new eh now, we would need to have +> this test. + +Commit 7b3a24c57d2eeda8dba9c205342b12689c4679f9 ("ahci: don't enable +port irq before handler is registered") caused a regression for CD-ROMs +attached to the IPR SATA bus on Power machines: + + ata_port_alloc: ENTER + ata_port_probe: ata1: bus probe begin + ata1.00: ata_dev_read_id: ENTER + ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40) + ata1.00: ata_dev_read_id: ENTER + ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40) + ata1.00: limiting speed to UDMA7:PIO5 + ata1.00: ata_dev_read_id: ENTER + ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40) + ata1.00: disabled + ata_port_probe: ata1: bus probe end + scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured + +The FROZEN flag added in that commit is only cleared by the new EH code, +which is not used by ipr. Clear this flag in the SAS code if we don't +support new EH. + +Reported-by: Benjamin Herrenschmidt +Signed-off-by: Nishanth Aravamudan +Signed-off-by: Jeff Garzik +--- + +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index d51f979..927f968 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -3797,6 +3797,12 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc); + */ + int ata_sas_port_start(struct ata_port *ap) + { ++ /* ++ * the port is marked as frozen at allocation time, but if we don't ++ * have new eh, we won't thaw it ++ */ ++ if (!ap->ops->error_handler) ++ ap->pflags &= ~ATA_PFLAG_FROZEN; + return 0; + } + EXPORT_SYMBOL_GPL(ata_sas_port_start); From d111c750cc6b38f8ad7d52520d97f742f4c58a3a Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 24 Jun 2011 17:02:32 -0400 Subject: [PATCH 88/99] Fix oopses in the CFQ disk scheduler (rhbz#577968) --- ...cking-around-ioc-ioc-data-assignment.patch | 44 +++++++++++++++++++ kernel.spec | 4 ++ 2 files changed, 48 insertions(+) create mode 100644 cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch diff --git a/cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch b/cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch new file mode 100644 index 000000000..bb04d63df --- /dev/null +++ b/cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch @@ -0,0 +1,44 @@ +From: Jens Axboe +Date: Sun, 5 Jun 2011 04:01:13 +0000 (+0200) +Subject: cfq-iosched: fix locking around ioc->ioc_data assignment +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ab4bd22d3cce6977dc039664cc2d052e3147d662 + +cfq-iosched: fix locking around ioc->ioc_data assignment + +Since we are modifying this RCU pointer, we need to hold +the lock protecting it around it. + +This fixes a potential reuse and double free of a cfq +io_context structure. The bug has been in CFQ for a long +time, it hit very few people but those it did hit seemed +to see it a lot. + +Tracked in RH bugzilla here: + +https://bugzilla.redhat.com/show_bug.cgi?id=577968 + +Credit goes to Paul Bolle for figuring out that the issue +was around the one-hit ioc->ioc_data cache. Thanks to his +hard work the issue is now fixed. + +Cc: stable@kernel.org +Signed-off-by: Jens Axboe +--- + +diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c +index 3c7b537..545b8d4 100644 +--- a/block/cfq-iosched.c ++++ b/block/cfq-iosched.c +@@ -2772,8 +2772,11 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, + smp_wmb(); + cic->key = cfqd_dead_key(cfqd); + +- if (ioc->ioc_data == cic) ++ if (rcu_dereference(ioc->ioc_data) == cic) { ++ spin_lock(&ioc->lock); + rcu_assign_pointer(ioc->ioc_data, NULL); ++ spin_unlock(&ioc->lock); ++ } + + if (cic->cfqq[BLK_RW_ASYNC]) { + cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); diff --git a/kernel.spec b/kernel.spec index 80ee3ca15..0339b7641 100644 --- a/kernel.spec +++ b/kernel.spec @@ -665,6 +665,7 @@ Patch580: linux-2.6-sparc-selinux-mprotect-checks.patch Patch600: block-queue-refcount.patch Patch601: block-export-blk_-get-put-_queue.patch Patch602: block-blkdev_get-should-access-bd_disk-only-after.patch +Patch603: cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch # libata Patch620: ahci-add-another-pci-id-for-marvell.patch @@ -1298,6 +1299,8 @@ ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch ApplyPatch block-queue-refcount.patch ApplyPatch block-export-blk_-get-put-_queue.patch ApplyPatch block-blkdev_get-should-access-bd_disk-only-after.patch +# rhbz#577968 +ApplyPatch cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch # libata ApplyPatch ahci-add-another-pci-id-for-marvell.patch @@ -2053,6 +2056,7 @@ fi - CVE-2011-2183: ksm: race between ksmd and exiting task - Revert 2.6.38.8 patch that broke magicmouse (rhbz#714381) - Fix drive detection failure on mvsas (rhbz#705019) +- Fix oopses in the CFQ disk scheduler (rhbz#577968) * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls From b67156cd9e4d538c6347c3ab82622e0e9e51a485 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 25 Jun 2011 02:19:38 -0400 Subject: [PATCH 89/99] Support Wacom touchscreen 00e6 in Thinkpad x220 (rhbz#708307) --- ...dd-support-for-lenovo-tablet-id-0xe6.patch | 36 +++++++++++++++++++ kernel.spec | 8 +++-- 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch diff --git a/input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch b/input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch new file mode 100644 index 000000000..f95908ed7 --- /dev/null +++ b/input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch @@ -0,0 +1,36 @@ +From: Manoj Iyer +Date: Fri, 1 Apr 2011 05:39:43 +0000 (-0700) +Subject: Input: wacom - add support for Lenovo tablet ID (0xE6) +X-Git-Tag: v2.6.39-rc2~4^2~1 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=26fcd2a7618db6c16be6aa3e56c0f3c25381e5a3 + +Input: wacom - add support for Lenovo tablet ID (0xE6) +[ 2.6.38 backport ] + +Signed-off-by: Manoj Iyer +Acked-by: Ping Cheng +Signed-off-by: Dmitry Torokhov +--- +RHBZ 708307 + +diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c +index c87d94f..08ba5ad 100644 +--- a/drivers/input/tablet/wacom_wac.c ++++ b/drivers/input/tablet/wacom_wac.c +@@ -1439,6 +1439,8 @@ static const struct wacom_features wacom_features_0xE2 = + { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; + static const struct wacom_features wacom_features_0xE3 = + { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; ++static const struct wacom_features wacom_features_0xE6 = ++ { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, 0, TABLETPC2FG }; + static const struct wacom_features wacom_features_0x47 = + { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; + static struct wacom_features wacom_features_0xD0 = +@@ -1561,6 +1564,7 @@ const struct usb_device_id wacom_ids[] = { + { USB_DEVICE_WACOM(0x9F) }, + { USB_DEVICE_WACOM(0xE2) }, + { USB_DEVICE_WACOM(0xE3) }, ++ { USB_DEVICE_WACOM(0xE6) }, + { USB_DEVICE_WACOM(0x47) }, + { USB_DEVICE_LENOVO(0x6004) }, + { } diff --git a/kernel.spec b/kernel.spec index 0339b7641..ceaf9fec9 100644 --- a/kernel.spec +++ b/kernel.spec @@ -651,6 +651,7 @@ Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch # revert 2.6.38.8 patch that broke magicmouse Patch453: hid-magicmouse-ignore-ivalid-report-id-while-switching.patch +Patch454: input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch Patch460: linux-2.6-serial-460800.patch @@ -1320,6 +1321,9 @@ ApplyPatch linux-2.6-input-kill-stupid-messages.patch ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch # Revert 2.6.38.8 patch that broke magicmouse ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching.patch -R +ApplyPatch input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch +ApplyPatch hid-ntrig-deref-unclaimed-input.patch +ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch # stop floppy.ko from autoloading during udev... ApplyPatch die-floppy-die.patch @@ -1426,9 +1430,6 @@ ApplyPatch bonding-incorrect-tx-queue-offset.patch ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch -ApplyPatch hid-ntrig-deref-unclaimed-input.patch - -ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch # rhbz#709122 @@ -2057,6 +2058,7 @@ fi - Revert 2.6.38.8 patch that broke magicmouse (rhbz#714381) - Fix drive detection failure on mvsas (rhbz#705019) - Fix oopses in the CFQ disk scheduler (rhbz#577968) +- Support Wacom touchscreen 00e6 in Thinkpad x220 (rhbz#708307) * Thu Jun 23 2011 Dave Airlie 2.6.38.8-34 - drm-i915-snb-irq-stalls-fix.patch: fix Sandybridge IRQ stalls From 198deb8acf9c91fc8b55779b848431aefd5a9965 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 25 Jun 2011 06:40:39 -0400 Subject: [PATCH 90/99] Intel IOMMU fixes from 2.6.39.2 --- ...-check-in-domain_remove_one_dev_info.patch | 37 ++++++++++++ ...for-identity-mapping-candidate-using.patch | 53 ++++++++++++++++ intel-iommu-dont-cache-iova-above-32bit.patch | 60 +++++++++++++++++++ intel-iommu-flush-unmaps-at-domain_exit.patch | 36 +++++++++++ ...nly-unlink-device-domains-from-iommu.patch | 48 +++++++++++++++ ...ve-host-bridge-devices-from-identity.patch | 44 ++++++++++++++ ...p-processing-of-the-identity_mapping.patch | 43 +++++++++++++ ...use-coherent-dma-mask-when-requested.patch | 35 +++++++++++ kernel.spec | 20 +++++++ 9 files changed, 376 insertions(+) create mode 100644 intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch create mode 100644 intel-iommu-check-for-identity-mapping-candidate-using.patch create mode 100644 intel-iommu-dont-cache-iova-above-32bit.patch create mode 100644 intel-iommu-flush-unmaps-at-domain_exit.patch create mode 100644 intel-iommu-only-unlink-device-domains-from-iommu.patch create mode 100644 intel-iommu-remove-host-bridge-devices-from-identity.patch create mode 100644 intel-iommu-speed-up-processing-of-the-identity_mapping.patch create mode 100644 intel-iommu-use-coherent-dma-mask-when-requested.patch diff --git a/intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch b/intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch new file mode 100644 index 000000000..ec494f626 --- /dev/null +++ b/intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch @@ -0,0 +1,37 @@ +From 8519dc4401ddf8a5399f979870bbeeadbc111186 Mon Sep 17 00:00:00 2001 +From: Mike Habeck +Date: Sat, 28 May 2011 13:15:07 -0500 +Subject: intel-iommu: Add domain check in domain_remove_one_dev_info + +From: Mike Habeck + +commit 8519dc4401ddf8a5399f979870bbeeadbc111186 upstream. + +The comment in domain_remove_one_dev_info() states "No need to compare +PCI domain; it has to be the same". But for the si_domain that isn't +going to be true, as it consists of all the PCI devices that are +identity mapped thus multiple PCI domains can be in si_domain. The +code needs to validate the PCI domain too. + +Signed-off-by: Mike Habeck +Signed-off-by: Mike Travis +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -3398,8 +3398,8 @@ static void domain_remove_one_dev_info(s + spin_lock_irqsave(&device_domain_lock, flags); + list_for_each_safe(entry, tmp, &domain->devices) { + info = list_entry(entry, struct device_domain_info, link); +- /* No need to compare PCI domain; it has to be the same */ +- if (info->bus == pdev->bus->number && ++ if (info->segment == pci_domain_nr(pdev->bus) && ++ info->bus == pdev->bus->number && + info->devfn == pdev->devfn) { + list_del(&info->link); + list_del(&info->global); diff --git a/intel-iommu-check-for-identity-mapping-candidate-using.patch b/intel-iommu-check-for-identity-mapping-candidate-using.patch new file mode 100644 index 000000000..50da53318 --- /dev/null +++ b/intel-iommu-check-for-identity-mapping-candidate-using.patch @@ -0,0 +1,53 @@ +From 8fcc5372fbac085199d84a880503ed67aba3fe49 Mon Sep 17 00:00:00 2001 +From: Chris Wright +Date: Sat, 28 May 2011 13:15:02 -0500 +Subject: intel-iommu: Check for identity mapping candidate using + system dma mask + +From: Chris Wright + +commit 8fcc5372fbac085199d84a880503ed67aba3fe49 upstream. + +The identity mapping code appears to make the assumption that if the +devices dma_mask is greater than 32bits the device can use identity +mapping. But that is not true: take the case where we have a 40bit +device in a 44bit architecture. The device can potentially receive a +physical address that it will truncate and cause incorrect addresses +to be used. + +Instead check to see if the device's dma_mask is large enough +to address the system's dma_mask. + +Signed-off-by: Mike Travis +Reviewed-by: Mike Habeck +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -2190,8 +2190,19 @@ static int iommu_should_identity_map(str + * Assume that they will -- if they turn out not to be, then we can + * take them out of the 1:1 domain later. + */ +- if (!startup) +- return pdev->dma_mask > DMA_BIT_MASK(32); ++ if (!startup) { ++ /* ++ * If the device's dma_mask is less than the system's memory ++ * size then this is not a candidate for identity mapping. ++ */ ++ u64 dma_mask = pdev->dma_mask; ++ ++ if (pdev->dev.coherent_dma_mask && ++ pdev->dev.coherent_dma_mask < dma_mask) ++ dma_mask = pdev->dev.coherent_dma_mask; ++ ++ return dma_mask >= dma_get_required_mask(&pdev->dev); ++ } + + return 1; + } diff --git a/intel-iommu-dont-cache-iova-above-32bit.patch b/intel-iommu-dont-cache-iova-above-32bit.patch new file mode 100644 index 000000000..4a2691e63 --- /dev/null +++ b/intel-iommu-dont-cache-iova-above-32bit.patch @@ -0,0 +1,60 @@ +From 1c9fc3d11b84fbd0c4f4aa7855702c2a1f098ebb Mon Sep 17 00:00:00 2001 +From: Chris Wright +Date: Sat, 28 May 2011 13:15:04 -0500 +Subject: intel-iommu: Dont cache iova above 32bit + +From: Chris Wright + +commit 1c9fc3d11b84fbd0c4f4aa7855702c2a1f098ebb upstream. + +Mike Travis and Mike Habeck reported an issue where iova allocation +would return a range that was larger than a device's dma mask. + +https://lkml.org/lkml/2011/3/29/423 + +The dmar initialization code will reserve all PCI MMIO regions and copy +those reservations into a domain specific iova tree. It is possible for +one of those regions to be above the dma mask of a device. It is typical +to allocate iovas with a 32bit mask (despite device's dma mask possibly +being larger) and cache the result until it exhausts the lower 32bit +address space. Freeing the iova range that is >= the last iova in the +lower 32bit range when there is still an iova above the 32bit range will +corrupt the cached iova by pointing it to a region that is above 32bit. +If that region is also larger than the device's dma mask, a subsequent +allocation will return an unusable iova and cause dma failure. + +Simply don't cache an iova that is above the 32bit caching boundary. + +Reported-by: Mike Travis +Reported-by: Mike Habeck +Acked-by: Mike Travis +Tested-by: Mike Habeck +Signed-off-by: Chris Wright +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/iova.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/pci/iova.c ++++ b/drivers/pci/iova.c +@@ -63,8 +63,16 @@ __cached_rbnode_delete_update(struct iov + curr = iovad->cached32_node; + cached_iova = container_of(curr, struct iova, node); + +- if (free->pfn_lo >= cached_iova->pfn_lo) +- iovad->cached32_node = rb_next(&free->node); ++ if (free->pfn_lo >= cached_iova->pfn_lo) { ++ struct rb_node *node = rb_next(&free->node); ++ struct iova *iova = container_of(node, struct iova, node); ++ ++ /* only cache if it's below 32bit pfn */ ++ if (node && iova->pfn_lo < iovad->dma_32bit_pfn) ++ iovad->cached32_node = node; ++ else ++ iovad->cached32_node = NULL; ++ } + } + + /* Computes the padding size required, to make the diff --git a/intel-iommu-flush-unmaps-at-domain_exit.patch b/intel-iommu-flush-unmaps-at-domain_exit.patch new file mode 100644 index 000000000..d08772a29 --- /dev/null +++ b/intel-iommu-flush-unmaps-at-domain_exit.patch @@ -0,0 +1,36 @@ +From 7b668357810ecb5fdda4418689d50f5d95aea6a8 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 24 May 2011 12:02:41 +0100 +Subject: intel-iommu: Flush unmaps at domain_exit + +From: Alex Williamson + +commit 7b668357810ecb5fdda4418689d50f5d95aea6a8 upstream. + +We typically batch unmaps to be lazily flushed out at +regular intervals. When we destroy a domain, we need +to force a flush of these lazy unmaps to be sure none +reference the domain we're about to free. + +Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=35062 +Signed-off-by: Alex Williamson +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -1416,6 +1416,10 @@ static void domain_exit(struct dmar_doma + if (!domain) + return; + ++ /* Flush any lazy unmaps that may reference this domain */ ++ if (!intel_iommu_strict) ++ flush_unmaps_timeout(0); ++ + domain_remove_dev_info(domain); + /* destroy iovas */ + put_iova_domain(&domain->iovad); diff --git a/intel-iommu-only-unlink-device-domains-from-iommu.patch b/intel-iommu-only-unlink-device-domains-from-iommu.patch new file mode 100644 index 000000000..839c56496 --- /dev/null +++ b/intel-iommu-only-unlink-device-domains-from-iommu.patch @@ -0,0 +1,48 @@ +From 9b4554b21ed07e8556405510638171f0c787742a Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Tue, 24 May 2011 12:19:04 -0400 +Subject: intel-iommu: Only unlink device domains from iommu + +From: Alex Williamson + +commit 9b4554b21ed07e8556405510638171f0c787742a upstream. + +Commit a97590e5 added unlinking domains from iommus to reciprocate the +iommu from domains unlinking that was already done. We actually want +to only do this for device domains and never for the static +identity map domain or VM domains. The SI domain is special and +never freed, while VM domain->id lives in their own special address +space, separate from iommu->domain_ids. + +In the current code, a VM can get domain->id zero, then mark that +domain unused when unbound from pci-stub. This leads to DMAR +write faults when the device is re-bound to the host driver. + +Signed-off-by: Alex Williamson +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -3422,10 +3422,13 @@ static void domain_remove_one_dev_info(s + domain_update_iommu_cap(domain); + spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); + +- spin_lock_irqsave(&iommu->lock, tmp_flags); +- clear_bit(domain->id, iommu->domain_ids); +- iommu->domains[domain->id] = NULL; +- spin_unlock_irqrestore(&iommu->lock, tmp_flags); ++ if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && ++ !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) { ++ spin_lock_irqsave(&iommu->lock, tmp_flags); ++ clear_bit(domain->id, iommu->domain_ids); ++ iommu->domains[domain->id] = NULL; ++ spin_unlock_irqrestore(&iommu->lock, tmp_flags); ++ } + } + + spin_unlock_irqrestore(&device_domain_lock, flags); diff --git a/intel-iommu-remove-host-bridge-devices-from-identity.patch b/intel-iommu-remove-host-bridge-devices-from-identity.patch new file mode 100644 index 000000000..66cef4a52 --- /dev/null +++ b/intel-iommu-remove-host-bridge-devices-from-identity.patch @@ -0,0 +1,44 @@ +From 825507d6d059f1cbe2503e0e5a3926225b983aec Mon Sep 17 00:00:00 2001 +From: Mike Travis +Date: Sat, 28 May 2011 13:15:06 -0500 +Subject: intel-iommu: Remove Host Bridge devices from identity + mapping + +From: Mike Travis + +commit 825507d6d059f1cbe2503e0e5a3926225b983aec upstream. + +When using the 1:1 (identity) PCI DMA remapping, PCI Host Bridge devices +that do not use the IOMMU causes a kernel panic. Fix that by not +inserting those devices into the si_domain. + +Signed-off-by: Mike Travis +Reviewed-by: Mike Habeck +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -46,6 +46,8 @@ + #define ROOT_SIZE VTD_PAGE_SIZE + #define CONTEXT_SIZE VTD_PAGE_SIZE + ++#define IS_BRIDGE_HOST_DEVICE(pdev) \ ++ ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST) + #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) + #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) + #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) +@@ -2217,6 +2219,9 @@ static int __init iommu_prepare_static_i + return -EFAULT; + + for_each_pci_dev(pdev) { ++ /* Skip Host/PCI Bridge devices */ ++ if (IS_BRIDGE_HOST_DEVICE(pdev)) ++ continue; + if (iommu_should_identity_map(pdev, 1)) { + printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n", + hw ? "hardware" : "software", pci_name(pdev)); diff --git a/intel-iommu-speed-up-processing-of-the-identity_mapping.patch b/intel-iommu-speed-up-processing-of-the-identity_mapping.patch new file mode 100644 index 000000000..9a2fd550e --- /dev/null +++ b/intel-iommu-speed-up-processing-of-the-identity_mapping.patch @@ -0,0 +1,43 @@ +From cb452a4040bb051d92e85d6e7eb60c11734c1781 Mon Sep 17 00:00:00 2001 +From: Mike Travis +Date: Sat, 28 May 2011 13:15:03 -0500 +Subject: intel-iommu: Speed up processing of the identity_mapping + function + +From: Mike Travis + +commit cb452a4040bb051d92e85d6e7eb60c11734c1781 upstream. + +When there are a large count of PCI devices, and the pass through +option for iommu is set, much time is spent in the identity_mapping +function hunting though the iommu domains to check if a specific +device is "identity mapped". + +Speed up the function by checking the cached info to see if +it's mapped to the static identity domain. + +Signed-off-by: Mike Travis +Reviewed-by: Mike Habeck +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -2109,10 +2109,10 @@ static int identity_mapping(struct pci_d + if (likely(!iommu_identity_mapping)) + return 0; + ++ info = pdev->dev.archdata.iommu; ++ if (info && info != DUMMY_DEVICE_DOMAIN_INFO) ++ return (info->domain == si_domain); + +- list_for_each_entry(info, &si_domain->devices, link) +- if (info->dev == pdev) +- return 1; + return 0; + } + diff --git a/intel-iommu-use-coherent-dma-mask-when-requested.patch b/intel-iommu-use-coherent-dma-mask-when-requested.patch new file mode 100644 index 000000000..01b43db74 --- /dev/null +++ b/intel-iommu-use-coherent-dma-mask-when-requested.patch @@ -0,0 +1,35 @@ +From c681d0ba1252954208220ad32248a3e8e2fc98e4 Mon Sep 17 00:00:00 2001 +From: Mike Travis +Date: Sat, 28 May 2011 13:15:05 -0500 +Subject: intel-iommu: Use coherent DMA mask when requested + +From: Mike Travis + +commit c681d0ba1252954208220ad32248a3e8e2fc98e4 upstream. + +The __intel_map_single function is not honoring the passed in DMA mask. +This results in not using the coherent DMA mask when called from +intel_alloc_coherent(). + +Signed-off-by: Mike Travis +Acked-by: Chris Wright +Reviewed-by: Mike Habeck +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/intel-iommu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/pci/intel-iommu.c ++++ b/drivers/pci/intel-iommu.c +@@ -2606,8 +2606,7 @@ static dma_addr_t __intel_map_single(str + iommu = domain_get_iommu(domain); + size = aligned_nrpages(paddr, size); + +- iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), +- pdev->dma_mask); ++ iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask); + if (!iova) + goto error; + diff --git a/kernel.spec b/kernel.spec index ceaf9fec9..4303c62cc 100644 --- a/kernel.spec +++ b/kernel.spec @@ -708,6 +708,14 @@ Patch1842: drm-radeon-pageflip-oops-fix.patch Patch1843: drm-radeon-update3.patch Patch1900: linux-2.6-intel-iommu-igfx.patch +Patch1901: intel-iommu-flush-unmaps-at-domain_exit.patch +Patch1902: intel-iommu-only-unlink-device-domains-from-iommu.patch +Patch1903: intel-iommu-check-for-identity-mapping-candidate-using.patch +Patch1904: intel-iommu-speed-up-processing-of-the-identity_mapping.patch +Patch1905: intel-iommu-dont-cache-iova-above-32bit.patch +Patch1906: intel-iommu-use-coherent-dma-mask-when-requested.patch +Patch1907: intel-iommu-remove-host-bridge-devices-from-identity.patch +Patch1908: intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch # linux1394 git patches Patch2200: linux-2.6-firewire-git-update.patch @@ -1231,6 +1239,15 @@ ApplyPatch x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available # # Intel IOMMU # +# from 2.6.39.2 +ApplyPatch intel-iommu-flush-unmaps-at-domain_exit.patch +ApplyPatch intel-iommu-only-unlink-device-domains-from-iommu.patch +ApplyPatch intel-iommu-check-for-identity-mapping-candidate-using.patch +ApplyPatch intel-iommu-speed-up-processing-of-the-identity_mapping.patch +ApplyPatch intel-iommu-dont-cache-iova-above-32bit.patch +ApplyPatch intel-iommu-use-coherent-dma-mask-when-requested.patch +ApplyPatch intel-iommu-remove-host-bridge-devices-from-identity.patch +ApplyPatch intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch # # PowerPC @@ -2049,6 +2066,9 @@ fi # and build. %changelog +* Sat Jun 25 2011 Chuck Ebbert +- Intel IOMMU fixes from 2.6.39.2 + * Fri Jun 24 2011 Chuck Ebbert - Minor cleanup: use upstream patch to export block_{get,put}_queue - block-blkdev_get-should-access-bd_disk-only-after.patch: From 0dd8943dd9b88ace501d878c4b45d8da56fd9048 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sat, 25 Jun 2011 10:33:52 -0400 Subject: [PATCH 91/99] Another fix for Sandybridge stalls --- ...rkaround-for-bsd-ring-on-sandybridge.patch | 43 +++++++++++++++++++ kernel.spec | 4 ++ 2 files changed, 47 insertions(+) create mode 100644 drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch diff --git a/drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch b/drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch new file mode 100644 index 000000000..06a8650b1 --- /dev/null +++ b/drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch @@ -0,0 +1,43 @@ +From: Chris Wilson +Date: Tue, 21 Jun 2011 17:37:59 +0000 (+0100) +Subject: drm/i915: Apply HWSTAM workaround for BSD ring on SandyBridge +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ec6a890dfed7dd245beba5e5bcdfcffbd934c284 + +drm/i915: Apply HWSTAM workaround for BSD ring on SandyBridge + +...we need to apply exactly the same workaround for missing interrupts +from BSD as for the BLT ring, apparently. + +See also commit 498e720b96379d8ee9c294950a01534a73defcf3 +(drm/i915: Fix gen6 (SNB) missed BLT ring interrupts). + +Reported-and-tested-by: nkalkhof@web.de +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38529 +Signed-off-by: Chris Wilson +Signed-off-by: Keith Packard +--- + +diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c +index 9e34a1a..ae2b499 100644 +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -1749,6 +1749,7 @@ void ironlake_irq_preinstall(struct drm_device *dev) + * happens. + */ + I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); ++ I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT); + } + + /* XXX hotplug from PCH */ +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index 2f967af..5d5def7 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -531,6 +531,7 @@ + #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 + #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) + ++#define GEN6_BSD_HWSTAM 0x12098 + #define GEN6_BSD_IMR 0x120a8 + #define GEN6_BSD_USER_INTERRUPT (1 << 12) + diff --git a/kernel.spec b/kernel.spec index 4303c62cc..bf9bfd447 100644 --- a/kernel.spec +++ b/kernel.spec @@ -700,6 +700,7 @@ Patch1826: drm-intel-edp-fixes.patch Patch1828: drm-intel-eeebox-eb1007-quirk.patch Patch1829: drm-intel-restore-mode.patch Patch1830: drm-i915-snb-irq-stalls-fix.patch +Patch1831: drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch # radeon - new hw + fixes for fusion and t500 regression Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch Patch1840: drm-radeon-update.patch @@ -1391,6 +1392,7 @@ ApplyPatch drm-i915-fix-pipelined-fencing.patch ApplyPatch drm-intel-eeebox-eb1007-quirk.patch ApplyPatch drm-intel-restore-mode.patch ApplyPatch drm-i915-snb-irq-stalls-fix.patch +ApplyPatch drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch # radeon DRM (add cayman support) ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -R @@ -2068,6 +2070,8 @@ fi %changelog * Sat Jun 25 2011 Chuck Ebbert - Intel IOMMU fixes from 2.6.39.2 +- drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch: + Another fix for Sandybridge stalls * Fri Jun 24 2011 Chuck Ebbert - Minor cleanup: use upstream patch to export block_{get,put}_queue From be7c8ca14b8d6be17bf1f98ce07ef7b6394598a3 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Sun, 26 Jun 2011 03:51:51 -0400 Subject: [PATCH 92/99] Use upstream Magicmouse patch --- ...ore-ivalid-report-id-while-switching.patch | 53 ------------------- kernel.spec | 11 ++-- ...ore-ivalid-report-id-while-switching.patch | 43 +++++++++++++++ 3 files changed, 47 insertions(+), 60 deletions(-) delete mode 100644 hid-magicmouse-ignore-ivalid-report-id-while-switching.patch create mode 100644 revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch diff --git a/hid-magicmouse-ignore-ivalid-report-id-while-switching.patch b/hid-magicmouse-ignore-ivalid-report-id-while-switching.patch deleted file mode 100644 index db1b48360..000000000 --- a/hid-magicmouse-ignore-ivalid-report-id-while-switching.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 23746a66d7d9e73402c68ef00d708796b97ebd72 Mon Sep 17 00:00:00 2001 -From: Jiri Kosina -Date: Thu, 19 May 2011 17:58:07 +0200 -Subject: HID: magicmouse: ignore 'ivalid report id' while switching - modes - -From: Jiri Kosina - -commit 23746a66d7d9e73402c68ef00d708796b97ebd72 upstream. - -The device reponds with 'invalid report id' when feature report switching it -into multitouch mode is sent to it. - -This has been silently ignored before 0825411ade ("HID: bt: Wait for ACK -on Sent Reports"), but since this commit, it propagates -EIO from the _raw -callback . - -So let the driver ignore -EIO as response to 0xd7,0x01 report, as that's -how the device reacts in normal mode. - -Sad, but following reality. - -This fixes https://bugzilla.kernel.org/show_bug.cgi?id=35022 - -Tested-by: Chase Douglas -Signed-off-by: Jiri Kosina -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/hid/hid-magicmouse.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - ---- a/drivers/hid/hid-magicmouse.c -+++ b/drivers/hid/hid-magicmouse.c -@@ -501,9 +501,17 @@ static int magicmouse_probe(struct hid_d - } - report->size = 6; - -+ /* -+ * The device reponds with 'invalid report id' when feature -+ * report switching it into multitouch mode is sent to it. -+ * -+ * This results in -EIO from the _raw low-level transport callback, -+ * but there seems to be no other way of switching the mode. -+ * Thus the super-ugly hacky success check below. -+ */ - ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), - HID_FEATURE_REPORT); -- if (ret != sizeof(feature)) { -+ if (ret != -EIO) { - hid_err(hdev, "unable to request touch data (%d)\n", ret); - goto err_stop_hw; - } diff --git a/kernel.spec b/kernel.spec index bf9bfd447..885f70839 100644 --- a/kernel.spec +++ b/kernel.spec @@ -649,9 +649,10 @@ Patch394: linux-2.6-acpi-debug-infinite-loop.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch -# revert 2.6.38.8 patch that broke magicmouse -Patch453: hid-magicmouse-ignore-ivalid-report-id-while-switching.patch +Patch453: revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch Patch454: input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch +Patch455: hid-ntrig-deref-unclaimed-input.patch +Patch456: hid-multitouch-add-support-for-elo-touchsystems.patch Patch460: linux-2.6-serial-460800.patch @@ -771,9 +772,6 @@ Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patc Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch -Patch12410: hid-ntrig-deref-unclaimed-input.patch - -Patch12415: hid-multitouch-add-support-for-elo-touchsystems.patch Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch @@ -1337,8 +1335,7 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch # The input layer spews crap no-one cares about. ApplyPatch linux-2.6-input-kill-stupid-messages.patch ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch -# Revert 2.6.38.8 patch that broke magicmouse -ApplyPatch hid-magicmouse-ignore-ivalid-report-id-while-switching.patch -R +ApplyPatch revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch ApplyPatch input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch ApplyPatch hid-ntrig-deref-unclaimed-input.patch ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch diff --git a/revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch b/revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch new file mode 100644 index 000000000..96be7fdd8 --- /dev/null +++ b/revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch @@ -0,0 +1,43 @@ +From: Jiri Kosina +Date: Thu, 16 Jun 2011 10:21:34 +0000 (+0200) +Subject: Revert "HID: magicmouse: ignore 'ivalid report id' while switching modes" +X-Git-Tag: v3.0-rc4~20^2 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=c3a4924565e2eecf2539871abd123d35be6d76d5 + +Revert "HID: magicmouse: ignore 'ivalid report id' while switching modes" + +This reverts commit 23746a66d7d9e73402c68ef00d708796b97ebd72. + +It turned out that the actual reason for failure is not the device +firmware, but bug in Bluetooth stack, which will be fixed by +patch by Ville Tervo which corrects the mask handling for CSR 1.1 +Dongles. + +Reported-and-tested-by: Ed Tomlinson +Reported-and-tested-by: Chase Douglas +Signed-off-by: Jiri Kosina +--- + +diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c +index a5eda4c..0ec91c1 100644 +--- a/drivers/hid/hid-magicmouse.c ++++ b/drivers/hid/hid-magicmouse.c +@@ -501,17 +501,9 @@ static int magicmouse_probe(struct hid_device *hdev, + } + report->size = 6; + +- /* +- * The device reponds with 'invalid report id' when feature +- * report switching it into multitouch mode is sent to it. +- * +- * This results in -EIO from the _raw low-level transport callback, +- * but there seems to be no other way of switching the mode. +- * Thus the super-ugly hacky success check below. +- */ + ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), + HID_FEATURE_REPORT); +- if (ret != -EIO) { ++ if (ret != sizeof(feature)) { + hid_err(hdev, "unable to request touch data (%d)\n", ret); + goto err_stop_hw; + } From 8bc042555b9e7dee3a95afc10fca06ff76010fed Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 27 Jun 2011 12:30:45 -0400 Subject: [PATCH 93/99] Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) --- Makefile | 2 -- config-debug | 2 -- config-generic | 2 ++ config-nodebug | 2 -- kernel.spec | 3 +++ 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 705670ff1..7bc3839f8 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,6 @@ debug: @perl -pi -e 's/# CONFIG_KDB_KEYBOARD is not set/CONFIG_KDB_KEYBOARD=y/' config-nodebug @perl -pi -e 's/# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set/CONFIG_CPU_NOTIFIER_ERROR_INJECT=m/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_PER_CPU_MAPS is not set/CONFIG_DEBUG_PER_CPU_MAPS=y/' config-nodebug - @perl -pi -e 's/CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y/# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set/' config-nodebug #@perl -pi -e 's/# CONFIG_PCI_DEFAULT_USE_CRS is not set/CONFIG_PCI_DEFAULT_USE_CRS=y/' config-nodebug @perl -pi -e 's/# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set/CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y/' config-nodebug @perl -pi -e 's/# CONFIG_TEST_LIST_SORT is not set/CONFIG_TEST_LIST_SORT=y/' config-nodebug @@ -168,7 +167,6 @@ release: #@perl -pi -e 's/CONFIG_KGDB_KDB=y/# CONFIG_KGDB_KDB is not set/' config-nodebug #@perl -pi -e 's/CONFIG_KDB_KEYBOARD=y/# CONFIG_KDB_KEYBOARD is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_PER_CPU_MAPS=y/# CONFIG_DEBUG_PER_CPU_MAPS is not set/' config-nodebug - @perl -pi -e 's/# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set/CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y/' config-nodebug #@perl -pi -e 's/CONFIG_PCI_DEFAULT_USE_CRS=y/# CONFIG_PCI_DEFAULT_USE_CRS is not set/' config-nodebug @perl -pi -e 's/CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y/# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set/' config-nodebug @perl -pi -e 's/CONFIG_TEST_LIST_SORT=y/# CONFIG_TEST_LIST_SORT is not set/' config-nodebug diff --git a/config-debug b/config-debug index 86aa2cc04..73017944b 100644 --- a/config-debug +++ b/config-debug @@ -88,8 +88,6 @@ CONFIG_PM_ADVANCED_DEBUG=y CONFIG_CEPH_LIB_PRETTYDEBUG=y CONFIG_QUOTA_DEBUG=y -# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set - CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y diff --git a/config-generic b/config-generic index d9a64445f..14d4e3783 100644 --- a/config-generic +++ b/config-generic @@ -3734,6 +3734,8 @@ CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_MANAGER_TESTS=y +# Note, CONFIG_CRYPTO_MANAGER_DISABLE_TESTS needs to be unset, or FIPS will be disabled. +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set CONFIG_CRYPTO_HW=y CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_MANAGER=m diff --git a/config-nodebug b/config-nodebug index c81b03b85..75101842a 100644 --- a/config-nodebug +++ b/config-nodebug @@ -88,8 +88,6 @@ CONFIG_PM_ADVANCED_DEBUG=y # CONFIG_CEPH_LIB_PRETTYDEBUG is not set # CONFIG_QUOTA_DEBUG is not set -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y - CONFIG_PCI_DEFAULT_USE_CRS=y CONFIG_KGDB_KDB=y diff --git a/kernel.spec b/kernel.spec index 885f70839..5211df656 100644 --- a/kernel.spec +++ b/kernel.spec @@ -2065,6 +2065,9 @@ fi # and build. %changelog +* Mon Jun 27 2011 Dave Jones +- Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) + * Sat Jun 25 2011 Chuck Ebbert - Intel IOMMU fixes from 2.6.39.2 - drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch: From 54043246c10bfb7ac51591b8fbdb2f655a6c16aa Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Wed, 29 Jun 2011 11:13:48 -0400 Subject: [PATCH 94/99] Cleanup - make crypto manager options match reality --- config-generic | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config-generic b/config-generic index 14d4e3783..6266d3742 100644 --- a/config-generic +++ b/config-generic @@ -3733,12 +3733,11 @@ CONFIG_CRYPTO=y CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y -CONFIG_CRYPTO_MANAGER_TESTS=y +CONFIG_CRYPTO_MANAGER=y # Note, CONFIG_CRYPTO_MANAGER_DISABLE_TESTS needs to be unset, or FIPS will be disabled. # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set CONFIG_CRYPTO_HW=y CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_MANAGER=m # CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_ARC4=m From a9318c93e69b8425badd23b34418dcaea0ba3845 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Thu, 30 Jun 2011 03:44:51 -0400 Subject: [PATCH 95/99] Add mainstream commitid to patch --- drm-radeon-pageflip-oops-fix.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drm-radeon-pageflip-oops-fix.patch b/drm-radeon-pageflip-oops-fix.patch index 785b61284..dd9cab813 100644 --- a/drm-radeon-pageflip-oops-fix.patch +++ b/drm-radeon-pageflip-oops-fix.patch @@ -1,4 +1,4 @@ -From ee11d4db3389aab9df38edb3eed4d5822320d5f1 Mon Sep 17 00:00:00 2001 +From 498c555f56a02ec1059bc150cde84411ba0ac010 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 29 May 2011 17:48:32 +1000 Subject: [PATCH] drm/radeon: fix oops in ttm reserve when pageflipping (v2) From 4efc3fff0056774a530ef1fda5cbf87fdfcada09 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 30 Jun 2011 14:18:36 -0400 Subject: [PATCH 96/99] 2.6.39 rebase --- TODO | 61 - acpi_reboot.patch | 106 - ahci-add-another-pci-id-for-marvell.patch | 32 - apple_backlight.patch | 688 -- ...le-fast-channel-switching-by-default.patch | 6 +- ...get-should-access-bd_disk-only-after.patch | 40 - block-export-blk_-get-put-_queue.patch | 39 - block-queue-refcount.patch | 43 - bonding-incorrect-tx-queue-offset.patch | 54 - config-arm | 12 + config-debug | 1 + config-generic | 226 +- config-ia64-generic | 5 + config-nodebug | 1 + config-powerpc-generic | 14 + config-powerpc32-generic | 3 +- config-powerpc64 | 4 + config-s390x | 5 + config-x86-generic | 29 +- config-x86_64-generic | 25 + cx88-Fix-HVR4000-IR-keymap.patch | 55 - drm-i915-fix-pipelined-fencing.patch | 80 - drm-intel-edp-fixes.patch | 14 +- drm-intel-eeebox-eb1007-quirk.patch | 36 - drm-intel-restore-mode.patch | 128 - drm-nouveau-updates.patch | 6777 --------------- drm-radeon-pageflip-oops-fix.patch | 69 - drm-radeon-update.patch | 4835 ----------- drm-radeon-update2.patch | 1708 ---- drm-radeon-update3.patch | 820 -- drm-ttm-move-notify.patch | 40 - efifb_update.patch | 217 - git-linus.diff | 0 ...uch-add-support-for-elo-touchsystems.patch | 2236 ++++- hid-ntrig-deref-unclaimed-input.patch | 46 - ...dd-support-for-lenovo-tablet-id-0xe6.patch | 36 - ...-check-in-domain_remove_one_dev_info.patch | 37 - ...for-identity-mapping-candidate-using.patch | 53 - intel-iommu-dont-cache-iova-above-32bit.patch | 60 - intel-iommu-flush-unmaps-at-domain_exit.patch | 36 - ...nly-unlink-device-domains-from-iommu.patch | 48 - ...ve-host-bridge-devices-from-identity.patch | 44 - ...p-processing-of-the-identity_mapping.patch | 43 - ...use-coherent-dma-mask-when-requested.patch | 35 - ...f-protection-on-5000-adapters-series.patch | 103 - kernel.spec | 118 +- linux-2.6-acpi-debug-infinite-loop.patch | 27 +- linux-2.6-crash-driver.patch | 22 +- linux-2.6-debug-always-inline-kzalloc.patch | 25 - linux-2.6-debug-sizeof-structs.patch | 33 - linux-2.6-hotfixes.patch | 15 - linux-2.6-i386-nx-emulation.patch | 14 +- linux-2.6-netconsole-deadlock.patch | 56 - linux-2.6-upstream-reverts.patch | 203 - linux-2.6-utrace-ptrace.patch | 778 +- linux-2.6-v4l-dvb-experimental.patch | 1326 --- linux-2.6-v4l-dvb-update.patch | 7725 ----------------- ...igured-for-aspm-under-powersave-mode.patch | 112 - ...ngle-valid-userspace-syslog-prefixes.patch | 214 - ..._sw-fix-deadlock-in-start_stop_endio.patch | 32 - sources | 3 +- ...info-when-frame-pointer-is-available.patch | 352 - 62 files changed, 2937 insertions(+), 27068 deletions(-) delete mode 100644 TODO delete mode 100644 acpi_reboot.patch delete mode 100644 ahci-add-another-pci-id-for-marvell.patch delete mode 100644 apple_backlight.patch delete mode 100644 block-blkdev_get-should-access-bd_disk-only-after.patch delete mode 100644 block-export-blk_-get-put-_queue.patch delete mode 100644 block-queue-refcount.patch delete mode 100644 bonding-incorrect-tx-queue-offset.patch delete mode 100644 cx88-Fix-HVR4000-IR-keymap.patch delete mode 100644 drm-i915-fix-pipelined-fencing.patch delete mode 100644 drm-intel-eeebox-eb1007-quirk.patch delete mode 100644 drm-intel-restore-mode.patch delete mode 100644 drm-radeon-pageflip-oops-fix.patch delete mode 100644 drm-radeon-update.patch delete mode 100644 drm-radeon-update2.patch delete mode 100644 drm-radeon-update3.patch delete mode 100644 drm-ttm-move-notify.patch delete mode 100644 efifb_update.patch delete mode 100644 git-linus.diff delete mode 100644 hid-ntrig-deref-unclaimed-input.patch delete mode 100644 input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch delete mode 100644 intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch delete mode 100644 intel-iommu-check-for-identity-mapping-candidate-using.patch delete mode 100644 intel-iommu-dont-cache-iova-above-32bit.patch delete mode 100644 intel-iommu-flush-unmaps-at-domain_exit.patch delete mode 100644 intel-iommu-only-unlink-device-domains-from-iommu.patch delete mode 100644 intel-iommu-remove-host-bridge-devices-from-identity.patch delete mode 100644 intel-iommu-speed-up-processing-of-the-identity_mapping.patch delete mode 100644 intel-iommu-use-coherent-dma-mask-when-requested.patch delete mode 100644 iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch delete mode 100644 linux-2.6-debug-always-inline-kzalloc.patch delete mode 100644 linux-2.6-debug-sizeof-structs.patch delete mode 100644 linux-2.6-hotfixes.patch delete mode 100644 linux-2.6-netconsole-deadlock.patch delete mode 100644 pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch delete mode 100644 printk-do-not-mangle-valid-userspace-syslog-prefixes.patch delete mode 100644 scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch delete mode 100644 x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch diff --git a/TODO b/TODO deleted file mode 100644 index abaefae05..000000000 --- a/TODO +++ /dev/null @@ -1,61 +0,0 @@ -# Put stuff likely to go upstream (in decreasing likelyhood) at the top. -# - -* linux-2.6-firewire-git-update.patch - perpetual updates from git trees. - -* linux-2.6-compile-fixes.patch -* linux-2.6-hotfixes.patch - Empty - -* linux-2.6-build-nonintconfig.patch -* linux-2.6-debug-nmi-timeout.patch -* linux-2.6-debug-spinlock-taint.patch -* linux-2.6-debug-taint-vm.patch -* linux-2.6-debug-vm-would-have-oomkilled.patch - TODO: Push upstream - -* linux-2.6-acpi-video-dos.patch -* linux-2.6-defaults-acpi-video.patch - Fedora policy decisions - Turn into CONFIG_ options and upstream ? - -* linux-2.6-crash-driver.patch - Unlikely to go upstream. - https://bugzilla.redhat.com/show_bug.cgi?id=492803 - -* linux-2.6-debug-always-inline-kzalloc.patch - Sent upstream Sep 25 2008 - -* linux-2.6-debug-sizeof-structs.patch - Fedora local debug stuff. - -* linux-2.6-utrace.patch - utrace - -* linux-2.6-defaults-pci_no_msi.patch - Fedora local choices uninteresting to upstream - -* linux-2.6-input-kill-stupid-messages.patch -* linux-2.6-silence-acpi-blacklist.patch -* linux-2.6-silence-fbcon-logo.patch -* linux-2.6-silence-noise.patch - Fedora local 'hush' patches. (Some will go upstream next time) - -* linux-2.6-execshield.patch - Not interesting to upstream. - -* lirc-2.6.33.patch -* hdpvr-ir-enable.patch - jarod working on upstreaming - -* linux-2.6-selinux-mprotect-checks.patch -* linux-2.6-sparc-selinux-mprotect-checks.patch - Newer version might go upstream at some point. - -* linux-2.6-serial-460800.patch - Probably not upstreamable. - http://marc.theaimsgroup.com/?l=linux-kernel&m=112687270832687&w=2 - https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=126403 - http://lkml.org/lkml/2006/8/2/208 - diff --git a/acpi_reboot.patch b/acpi_reboot.patch deleted file mode 100644 index 82bffaa64..000000000 --- a/acpi_reboot.patch +++ /dev/null @@ -1,106 +0,0 @@ -Improve our reboot handling for compatibility with Windows. - -Upstream commits: -660e34cebf0a11d54f2d5dd8838607452355f321 -f17d9cbf20c4734c4199caa6dee87047f2f8278f - -diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c -index c495aa8..c770e66 100644 ---- a/arch/x86/kernel/reboot.c -+++ b/arch/x86/kernel/reboot.c -@@ -34,7 +34,7 @@ EXPORT_SYMBOL(pm_power_off); - - static const struct desc_ptr no_idt = {}; - static int reboot_mode; --enum reboot_type reboot_type = BOOT_KBD; -+enum reboot_type reboot_type = BOOT_ACPI; - int reboot_force; - - #if defined(CONFIG_X86_32) && defined(CONFIG_SMP) -@@ -538,9 +538,23 @@ void __attribute__((weak)) mach_reboot_fixups(void) - { - } - -+/* -+ * Windows does the following on reboot: -+ * 1) If the FADT has the ACPI reboot register flag set, try it -+ * 2) If still alive, write to the keyboard controller -+ * 3) If still alive, write to the ACPI reboot register again -+ * 4) Ig still alive, write to the keyboard controller again -+ * -+ * If the machine is still alive at this stage, it gives up. We default to -+ * following the same pattern, except that if we're still alive after (4) we'll -+ * try to force a triple fault and then cycle between hitting the keyboard -+ * controller and doing that -+ */ - static void native_machine_emergency_restart(void) - { - int i; -+ int attempt = 0; -+ int orig_reboot_type = reboot_type; - - if (reboot_emergency) - emergency_vmx_disable_all(); -@@ -562,6 +576,13 @@ static void native_machine_emergency_restart(void) - outb(0xfe, 0x64); /* pulse reset low */ - udelay(50); - } -+ if (attempt == 0 && orig_reboot_type == BOOT_ACPI) { -+ attempt = 1; -+ reboot_type = BOOT_ACPI; -+ } else { -+ reboot_type = BOOT_TRIPLE; -+ } -+ break; - - case BOOT_TRIPLE: - load_idt(&no_idt); -diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c -index 50cc3be..c6a4e63 100644 ---- a/drivers/acpi/acpica/hwxface.c -+++ b/drivers/acpi/acpica/hwxface.c -@@ -82,12 +82,11 @@ acpi_status acpi_reset(void) - /* - * For I/O space, write directly to the OSL. This bypasses the port - * validation mechanism, which may block a valid write to the reset -- * register. -+ * register. Spec section 4.7.3.6 requires register width to be 8. - */ - status = - acpi_os_write_port((acpi_io_address) reset_reg->address, -- acpi_gbl_FADT.reset_value, -- reset_reg->bit_width); -+ acpi_gbl_FADT.reset_value, 8); - } else { - /* Write the reset value to the reset register */ - -diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c -index 93f9114..a6c77e8b 100644 ---- a/drivers/acpi/reboot.c -+++ b/drivers/acpi/reboot.c -@@ -15,9 +15,15 @@ void acpi_reboot(void) - - rr = &acpi_gbl_FADT.reset_register; - -- /* Is the reset register supported? */ -- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || -- rr->bit_width != 8 || rr->bit_offset != 0) -+ /* ACPI reset register was only introduced with v2 of the FADT */ -+ -+ if (acpi_gbl_FADT.header.revision < 2) -+ return; -+ -+ /* Is the reset register supported? The spec says we should be -+ * checking the bit width and bit offset, but Windows ignores -+ * these fields */ -+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER)) - return; - - reset_value = acpi_gbl_FADT.reset_value; -@@ -45,6 +51,4 @@ void acpi_reboot(void) - acpi_reset(); - break; - } -- /* Wait ten seconds */ -- acpi_os_stall(10000000); - } diff --git a/ahci-add-another-pci-id-for-marvell.patch b/ahci-add-another-pci-id-for-marvell.patch deleted file mode 100644 index e7ac983fa..000000000 --- a/ahci-add-another-pci-id-for-marvell.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Tejun Heo -Date: Mon, 29 Nov 2010 14:57:14 +0000 (+0100) -Subject: ahci: add another PCI ID for marvell -X-Git-Tag: v2.6.39-rc1~490^2 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=50be5e3657cd2851a297dc0b3fd459f25829d29b - -ahci: add another PCI ID for marvell - -1b4b:91a3 seems to be another PCI ID for marvell ahci. Add it. -Reported and tested in the following thread. - - http://thread.gmane.org/gmane.linux.kernel/1068354 - -Signed-off-by: Tejun Heo -Reported-by: Borislav Petkov -Reported-by: Alessandro Tagliapietra -Signed-off-by: Jeff Garzik ---- - -diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c -index 0c22ebd..e62f693 100644 ---- a/drivers/ata/ahci.c -+++ b/drivers/ata/ahci.c -@@ -385,6 +385,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { - .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ - { PCI_DEVICE(0x1b4b, 0x9125), - .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ -+ { PCI_DEVICE(0x1b4b, 0x91a3), -+ .driver_data = board_ahci_yes_fbs }, - - /* Promise */ - { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ diff --git a/apple_backlight.patch b/apple_backlight.patch deleted file mode 100644 index c7d5a8191..000000000 --- a/apple_backlight.patch +++ /dev/null @@ -1,688 +0,0 @@ -Various fixes to the Apple backlight driver. Upstream in .38? - -diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig -index e54a337..fb5df46 100644 ---- a/drivers/video/backlight/Kconfig -+++ b/drivers/video/backlight/Kconfig -@@ -236,12 +236,12 @@ config BACKLIGHT_MAX8925 - If you have a LCD backlight connected to the WLED output of MAX8925 - WLED output, say Y here to enable this driver. - --config BACKLIGHT_MBP_NVIDIA -- tristate "MacBook Pro Nvidia Backlight Driver" -+config BACKLIGHT_APPLE -+ tristate "Apple Backlight Driver" - depends on X86 - help -- If you have an Apple Macbook Pro with Nvidia graphics hardware say Y -- to enable a driver for its backlight -+ If you have an Intel-based Apple say Y to enable a driver for its -+ backlight - - config BACKLIGHT_TOSA - tristate "Sharp SL-6000 Backlight Driver" -diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile -index 44c0f81..ebaecc0 100644 ---- a/drivers/video/backlight/Makefile -+++ b/drivers/video/backlight/Makefile -@@ -26,7 +26,7 @@ obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o - obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o - obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o - obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o --obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o -+obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o - obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o - obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o - obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o -diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c -new file mode 100644 -index 0000000..8f808c7 ---- /dev/null -+++ b/drivers/video/backlight/apple_bl.c -@@ -0,0 +1,240 @@ -+/* -+ * Backlight Driver for Intel-based Apples -+ * -+ * Copyright (c) Red Hat -+ * Based on code from Pommed: -+ * Copyright (C) 2006 Nicolas Boichat -+ * Copyright (C) 2006 Felipe Alfaro Solana -+ * Copyright (C) 2007 Julien BLACHE -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This driver triggers SMIs which cause the firmware to change the -+ * backlight brightness. This is icky in many ways, but it's impractical to -+ * get at the firmware code in order to figure out what it's actually doing. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct backlight_device *apple_backlight_device; -+ -+struct hw_data { -+ /* I/O resource to allocate. */ -+ unsigned long iostart; -+ unsigned long iolen; -+ /* Backlight operations structure. */ -+ const struct backlight_ops backlight_ops; -+ void (*set_brightness)(int); -+}; -+ -+static const struct hw_data *hw_data; -+ -+#define DRIVER "apple_backlight: " -+ -+/* Module parameters. */ -+static int debug; -+module_param_named(debug, debug, int, 0644); -+MODULE_PARM_DESC(debug, "Set to one to enable debugging messages."); -+ -+/* -+ * Implementation for machines with Intel chipset. -+ */ -+static void intel_chipset_set_brightness(int intensity) -+{ -+ outb(0x04 | (intensity << 4), 0xb3); -+ outb(0xbf, 0xb2); -+} -+ -+static int intel_chipset_send_intensity(struct backlight_device *bd) -+{ -+ int intensity = bd->props.brightness; -+ -+ if (debug) -+ printk(KERN_DEBUG DRIVER "setting brightness to %d\n", -+ intensity); -+ -+ intel_chipset_set_brightness(intensity); -+ return 0; -+} -+ -+static int intel_chipset_get_intensity(struct backlight_device *bd) -+{ -+ int intensity; -+ -+ outb(0x03, 0xb3); -+ outb(0xbf, 0xb2); -+ intensity = inb(0xb3) >> 4; -+ -+ if (debug) -+ printk(KERN_DEBUG DRIVER "read brightness of %d\n", -+ intensity); -+ -+ return intensity; -+} -+ -+static const struct hw_data intel_chipset_data = { -+ .iostart = 0xb2, -+ .iolen = 2, -+ .backlight_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .get_brightness = intel_chipset_get_intensity, -+ .update_status = intel_chipset_send_intensity, -+ }, -+ .set_brightness = intel_chipset_set_brightness, -+}; -+ -+/* -+ * Implementation for machines with Nvidia chipset. -+ */ -+static void nvidia_chipset_set_brightness(int intensity) -+{ -+ outb(0x04 | (intensity << 4), 0x52f); -+ outb(0xbf, 0x52e); -+} -+ -+static int nvidia_chipset_send_intensity(struct backlight_device *bd) -+{ -+ int intensity = bd->props.brightness; -+ -+ if (debug) -+ printk(KERN_DEBUG DRIVER "setting brightness to %d\n", -+ intensity); -+ -+ nvidia_chipset_set_brightness(intensity); -+ return 0; -+} -+ -+static int nvidia_chipset_get_intensity(struct backlight_device *bd) -+{ -+ int intensity; -+ -+ outb(0x03, 0x52f); -+ outb(0xbf, 0x52e); -+ intensity = inb(0x52f) >> 4; -+ -+ if (debug) -+ printk(KERN_DEBUG DRIVER "read brightness of %d\n", -+ intensity); -+ -+ return intensity; -+} -+ -+static const struct hw_data nvidia_chipset_data = { -+ .iostart = 0x52e, -+ .iolen = 2, -+ .backlight_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .get_brightness = nvidia_chipset_get_intensity, -+ .update_status = nvidia_chipset_send_intensity -+ }, -+ .set_brightness = nvidia_chipset_set_brightness, -+}; -+ -+static int __devinit apple_bl_add(struct acpi_device *dev) -+{ -+ struct backlight_properties props; -+ struct pci_dev *host; -+ int intensity; -+ -+ host = pci_get_bus_and_slot(0, 0); -+ -+ if (!host) { -+ printk(KERN_ERR DRIVER "unable to find PCI host\n"); -+ return -ENODEV; -+ } -+ -+ if (host->vendor == PCI_VENDOR_ID_INTEL) -+ hw_data = &intel_chipset_data; -+ else if (host->vendor == PCI_VENDOR_ID_NVIDIA) -+ hw_data = &nvidia_chipset_data; -+ -+ pci_dev_put(host); -+ -+ if (!hw_data) { -+ printk(KERN_ERR DRIVER "unknown hardware\n"); -+ return -ENODEV; -+ } -+ -+ /* Check that the hardware responds - this may not work under EFI */ -+ -+ intensity = hw_data->backlight_ops.get_brightness(NULL); -+ -+ if (!intensity) { -+ hw_data->set_brightness(1); -+ if (!hw_data->backlight_ops.get_brightness(NULL)) -+ return -ENODEV; -+ -+ hw_data->set_brightness(0); -+ } -+ -+ if (!request_region(hw_data->iostart, hw_data->iolen, -+ "Apple backlight")) -+ return -ENXIO; -+ -+ memset(&props, 0, sizeof(struct backlight_properties)); -+ props.max_brightness = 15; -+ apple_backlight_device = backlight_device_register("apple_backlight", -+ NULL, NULL, &hw_data->backlight_ops, &props); -+ -+ if (IS_ERR(apple_backlight_device)) { -+ release_region(hw_data->iostart, hw_data->iolen); -+ return PTR_ERR(apple_backlight_device); -+ } -+ -+ apple_backlight_device->props.brightness = -+ hw_data->backlight_ops.get_brightness(apple_backlight_device); -+ backlight_update_status(apple_backlight_device); -+ -+ return 0; -+} -+ -+static int __devexit apple_bl_remove(struct acpi_device *dev, int type) -+{ -+ backlight_device_unregister(apple_backlight_device); -+ -+ release_region(hw_data->iostart, hw_data->iolen); -+ hw_data = NULL; -+ return 0; -+} -+ -+static const struct acpi_device_id apple_bl_ids[] = { -+ {"APP0002", 0}, -+ {"", 0}, -+}; -+ -+static struct acpi_driver apple_bl_driver = { -+ .name = "Apple backlight", -+ .ids = apple_bl_ids, -+ .ops = { -+ .add = apple_bl_add, -+ .remove = apple_bl_remove, -+ }, -+}; -+ -+static int __init apple_bl_init(void) -+{ -+ return acpi_bus_register_driver(&apple_bl_driver); -+} -+ -+static void __exit apple_bl_exit(void) -+{ -+ acpi_bus_unregister_driver(&apple_bl_driver); -+} -+ -+module_init(apple_bl_init); -+module_exit(apple_bl_exit); -+ -+MODULE_AUTHOR("Matthew Garrett "); -+MODULE_DESCRIPTION("Apple Backlight Driver"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(acpi, apple_bl_ids); -+MODULE_ALIAS("mbp_nvidia_bl"); -diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c -deleted file mode 100644 -index 1485f73..0000000 ---- a/drivers/video/backlight/mbp_nvidia_bl.c -+++ /dev/null -@@ -1,400 +0,0 @@ --/* -- * Backlight Driver for Nvidia 8600 in Macbook Pro -- * -- * Copyright (c) Red Hat -- * Based on code from Pommed: -- * Copyright (C) 2006 Nicolas Boichat -- * Copyright (C) 2006 Felipe Alfaro Solana -- * Copyright (C) 2007 Julien BLACHE -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- * -- * This driver triggers SMIs which cause the firmware to change the -- * backlight brightness. This is icky in many ways, but it's impractical to -- * get at the firmware code in order to figure out what it's actually doing. -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include -- --static struct backlight_device *mbp_backlight_device; -- --/* Structure to be passed to the DMI_MATCH function. */ --struct dmi_match_data { -- /* I/O resource to allocate. */ -- unsigned long iostart; -- unsigned long iolen; -- /* Backlight operations structure. */ -- const struct backlight_ops backlight_ops; --}; -- --/* Module parameters. */ --static int debug; --module_param_named(debug, debug, int, 0644); --MODULE_PARM_DESC(debug, "Set to one to enable debugging messages."); -- --/* -- * Implementation for MacBooks with Intel chipset. -- */ --static int intel_chipset_send_intensity(struct backlight_device *bd) --{ -- int intensity = bd->props.brightness; -- -- if (debug) -- printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n", -- intensity); -- -- outb(0x04 | (intensity << 4), 0xb3); -- outb(0xbf, 0xb2); -- return 0; --} -- --static int intel_chipset_get_intensity(struct backlight_device *bd) --{ -- int intensity; -- -- outb(0x03, 0xb3); -- outb(0xbf, 0xb2); -- intensity = inb(0xb3) >> 4; -- -- if (debug) -- printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n", -- intensity); -- -- return intensity; --} -- --static const struct dmi_match_data intel_chipset_data = { -- .iostart = 0xb2, -- .iolen = 2, -- .backlight_ops = { -- .options = BL_CORE_SUSPENDRESUME, -- .get_brightness = intel_chipset_get_intensity, -- .update_status = intel_chipset_send_intensity, -- } --}; -- --/* -- * Implementation for MacBooks with Nvidia chipset. -- */ --static int nvidia_chipset_send_intensity(struct backlight_device *bd) --{ -- int intensity = bd->props.brightness; -- -- if (debug) -- printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n", -- intensity); -- -- outb(0x04 | (intensity << 4), 0x52f); -- outb(0xbf, 0x52e); -- return 0; --} -- --static int nvidia_chipset_get_intensity(struct backlight_device *bd) --{ -- int intensity; -- -- outb(0x03, 0x52f); -- outb(0xbf, 0x52e); -- intensity = inb(0x52f) >> 4; -- -- if (debug) -- printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n", -- intensity); -- -- return intensity; --} -- --static const struct dmi_match_data nvidia_chipset_data = { -- .iostart = 0x52e, -- .iolen = 2, -- .backlight_ops = { -- .options = BL_CORE_SUSPENDRESUME, -- .get_brightness = nvidia_chipset_get_intensity, -- .update_status = nvidia_chipset_send_intensity -- } --}; -- --/* -- * DMI matching. -- */ --static /* const */ struct dmi_match_data *driver_data; -- --static int mbp_dmi_match(const struct dmi_system_id *id) --{ -- driver_data = id->driver_data; -- -- printk(KERN_INFO "mbp_nvidia_bl: %s detected\n", id->ident); -- return 1; --} -- --static const struct dmi_system_id __initdata mbp_device_table[] = { -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 1,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 2,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 3,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook3,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 4,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 4,2", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 1,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 1,2", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,2"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 2,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 2,2", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 3,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 3,2", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 4,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookAir 1,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir1,1"), -- }, -- .driver_data = (void *)&intel_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 5,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,1"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 5,2", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBook 6,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookAir 2,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2,1"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 5,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 5,2", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,2"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 5,3", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 5,4", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookPro 5,5", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,5"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookAir 3,1", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,1"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { -- .callback = mbp_dmi_match, -- .ident = "MacBookAir 3,2", -- .matches = { -- DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -- DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,2"), -- }, -- .driver_data = (void *)&nvidia_chipset_data, -- }, -- { } --}; -- --static int __init mbp_init(void) --{ -- struct backlight_properties props; -- if (!dmi_check_system(mbp_device_table)) -- return -ENODEV; -- -- if (!request_region(driver_data->iostart, driver_data->iolen, -- "Macbook Pro backlight")) -- return -ENXIO; -- -- memset(&props, 0, sizeof(struct backlight_properties)); -- props.max_brightness = 15; -- mbp_backlight_device = backlight_device_register("mbp_backlight", NULL, -- NULL, -- &driver_data->backlight_ops, -- &props); -- if (IS_ERR(mbp_backlight_device)) { -- release_region(driver_data->iostart, driver_data->iolen); -- return PTR_ERR(mbp_backlight_device); -- } -- -- mbp_backlight_device->props.brightness = -- driver_data->backlight_ops.get_brightness(mbp_backlight_device); -- backlight_update_status(mbp_backlight_device); -- -- return 0; --} -- --static void __exit mbp_exit(void) --{ -- backlight_device_unregister(mbp_backlight_device); -- -- release_region(driver_data->iostart, driver_data->iolen); --} -- --module_init(mbp_init); --module_exit(mbp_exit); -- --MODULE_AUTHOR("Matthew Garrett "); --MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver"); --MODULE_LICENSE("GPL"); --MODULE_DEVICE_TABLE(dmi, mbp_device_table); diff --git a/ath5k-disable-fast-channel-switching-by-default.patch b/ath5k-disable-fast-channel-switching-by-default.patch index 86ebf8340..a26eb51d9 100644 --- a/ath5k-disable-fast-channel-switching-by-default.patch +++ b/ath5k-disable-fast-channel-switching-by-default.patch @@ -40,10 +40,10 @@ index 09ae4ef..0fb6333 100644 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); -@@ -2685,7 +2691,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, +@@ -2669,7 +2669,8 @@ ath5k_reset(struct ath5k_softc *sc, stru + ath5k_drain_tx_buffs(sc); + if (chan) sc->curchan = chan; - sc->curband = &sc->sbands[chan->band]; - } - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, + fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, diff --git a/block-blkdev_get-should-access-bd_disk-only-after.patch b/block-blkdev_get-should-access-bd_disk-only-after.patch deleted file mode 100644 index 956b04160..000000000 --- a/block-blkdev_get-should-access-bd_disk-only-after.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 4c49ff3fe128ca68dabd07537415c419ad7f82f9 Mon Sep 17 00:00:00 2001 -From: Tejun Heo -Date: Wed, 1 Jun 2011 08:27:41 +0200 -Subject: block: blkdev_get() should access ->bd_disk only after - success - -From: Tejun Heo - -commit 4c49ff3fe128ca68dabd07537415c419ad7f82f9 upstream. - -d4dc210f69 (block: don't block events on excl write for non-optical -devices) added dereferencing of bdev->bd_disk to test -GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE; however, bdev->bd_disk can be -%NULL if open failed which can lead to an oops. - -Test the flag after testing open was successful, not before. - -Signed-off-by: Tejun Heo -Reported-by: David Miller -Tested-by: David Miller -Signed-off-by: Jens Axboe -Signed-off-by: Greg Kroah-Hartman - ---- - fs/block_dev.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/fs/block_dev.c -+++ b/fs/block_dev.c -@@ -1272,8 +1272,8 @@ int blkdev_get(struct block_device *bdev - * individual writeable reference is too fragile given the - * way @mode is used in blkdev_get/put(). - */ -- if ((disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE) && -- !res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) { -+ if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder && -+ (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) { - bdev->bd_write_holder = true; - disk_block_events(disk); - } diff --git a/block-export-blk_-get-put-_queue.patch b/block-export-blk_-get-put-_queue.patch deleted file mode 100644 index 05db7bd20..000000000 --- a/block-export-blk_-get-put-_queue.patch +++ /dev/null @@ -1,39 +0,0 @@ -From d86e0e83b32bc84600adb0b6ea1fce389b266682 Mon Sep 17 00:00:00 2001 -From: Jens Axboe -Date: Fri, 27 May 2011 07:44:43 +0200 -Subject: block: export blk_{get,put}_queue() - -From: Jens Axboe - -commit d86e0e83b32bc84600adb0b6ea1fce389b266682 upstream. -[ backport to 2.6.38 ] - -We need them in SCSI to fix a bug, but currently they are not -exported to modules. Export them. - -Signed-off-by: Jens Axboe -Signed-off-by: Greg Kroah-Hartman -Signed-off-by: Chuck Ebbert - ---- - block/blk-core.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/block/blk-core.c -+++ b/block/blk-core.c -@@ -345,6 +345,7 @@ void blk_put_queue(struct request_queue - { - kobject_put(&q->kobj); - } -+EXPORT_SYMBOL(blk_put_queue); - - void blk_cleanup_queue(struct request_queue *q) - { -@@ -566,6 +567,7 @@ int blk_get_queue(struct request_queue * - - return 1; - } -+EXPORT_SYMBOL(blk_get_queue); - - static inline void blk_free_request(struct request_queue *q, struct request *rq) - { diff --git a/block-queue-refcount.patch b/block-queue-refcount.patch deleted file mode 100644 index d53dd1bac..000000000 --- a/block-queue-refcount.patch +++ /dev/null @@ -1,43 +0,0 @@ -commit e73e079bf128d68284efedeba1fbbc18d78610f9 -Author: James Bottomley -Date: Wed May 25 15:52:14 2011 -0500 - - [SCSI] Fix oops caused by queue refcounting failure - - In certain circumstances, we can get an oops from a torn down device. - Most notably this is from CD roms trying to call scsi_ioctl. The root - cause of the problem is the fact that after scsi_remove_device() has - been called, the queue is fully torn down. This is actually wrong - since the queue can be used until the sdev release function is called. - Therefore, we add an extra reference to the queue which is released in - sdev->release, so the queue always exists. - - Reported-by: Parag Warudkar - Cc: stable@kernel.org - Signed-off-by: James Bottomley - -diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c -index 58584dc..44e8ca3 100644 ---- a/drivers/scsi/scsi_scan.c -+++ b/drivers/scsi/scsi_scan.c -@@ -297,7 +297,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, - kfree(sdev); - goto out; - } -- -+ blk_get_queue(sdev->request_queue); - sdev->request_queue->queuedata = sdev; - scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); - -diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c -index e639125..e0bd3f7 100644 ---- a/drivers/scsi/scsi_sysfs.c -+++ b/drivers/scsi/scsi_sysfs.c -@@ -322,6 +322,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) - kfree(evt); - } - -+ blk_put_queue(sdev->request_queue); - /* NULL queue means the device can't be used */ - sdev->request_queue = NULL; - diff --git a/bonding-incorrect-tx-queue-offset.patch b/bonding-incorrect-tx-queue-offset.patch deleted file mode 100644 index ebc33de4f..000000000 --- a/bonding-incorrect-tx-queue-offset.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Phil Oester -Date: Mon, 14 Mar 2011 06:22:04 +0000 (+0000) -Subject: bonding: Incorrect TX queue offset -X-Git-Tag: v2.6.39-rc1~468^2~15 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=fd0e435b0fe85622f167b84432552885a4856ac8 - -bonding: Incorrect TX queue offset - -When packets come in from a device with >= 16 receive queues -headed out a bonding interface, syslog gets filled with this: - - kernel: bond0 selects TX queue 16, but real number of TX queues is 16 - -because queue_mapping is offset by 1. Adjust return value -to account for the offset. - -This is a revision of my earlier patch (which did not use the -skb_rx_queue_* helpers - thanks to Ben for the suggestion). -Andy submitted a similar patch which emits a pr_warning on -invalid queue selection, but I believe the log spew is -not useful. We can revisit that question in the future, -but in the interim I believe fixing the core problem is -worthwhile. - -Signed-off-by: Phil Oester -Signed-off-by: Andy Gospodarek -Signed-off-by: David S. Miller ---- - -diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c -index 3ad4f50..a93d941 100644 ---- a/drivers/net/bonding/bond_main.c -+++ b/drivers/net/bonding/bond_main.c -@@ -4341,11 +4341,18 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) - { - /* - * This helper function exists to help dev_pick_tx get the correct -- * destination queue. Using a helper function skips the a call to -+ * destination queue. Using a helper function skips a call to - * skb_tx_hash and will put the skbs in the queue we expect on their - * way down to the bonding driver. - */ -- return skb->queue_mapping; -+ u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0; -+ -+ if (unlikely(txq >= dev->real_num_tx_queues)) { -+ do -+ txq -= dev->real_num_tx_queues; -+ while (txq >= dev->real_num_tx_queues); -+ } -+ return txq; - } - - static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) diff --git a/config-arm b/config-arm index 47a024d9f..dd6f90ad6 100644 --- a/config-arm +++ b/config-arm @@ -135,3 +135,15 @@ CONFIG_STRICT_DEVMEM=y # CONFIG_HVC_DCC is not set CONFIG_SPARSE_IRQ=y + +# CONFIG_ARM_PATCH_PHYS_VIRT is not set + +CONFIG_FTMAC100=m + +CONFIG_HWSPINLOCK_OMAP=m + +CONFIG_USE_OF=y +CONFIG_PROC_DEVICETREE=y +CONFIG_MTD_PHYSMAP_OF=m +CONFIG_SERIAL_OF_PLATFORM=m +CONFIG_MMC_SDHCI_OF=m diff --git a/config-debug b/config-debug index 73017944b..7bbaa0b59 100644 --- a/config-debug +++ b/config-debug @@ -41,6 +41,7 @@ CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set CONFIG_DEBUG_OBJECTS_FREE=y CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 CONFIG_X86_PTDUMP=y diff --git a/config-generic b/config-generic index 6266d3742..83a056bfa 100644 --- a/config-generic +++ b/config-generic @@ -6,6 +6,7 @@ CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y CONFIG_LOCALVERSION="" CONFIG_CROSS_COMPILE="" +CONFIG_DEFAULT_HOSTNAME="(none)" # # Code maturity level options @@ -32,6 +33,7 @@ CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_FHANDLE=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y @@ -138,6 +140,7 @@ CONFIG_MMC_SDHCI_PLTFM=m CONFIG_MMC_CB710=m CONFIG_MMC_RICOH_MMC=y CONFIG_MMC_USHC=m +CONFIG_MMC_VUB300=m CONFIG_CB710_CORE=m # CONFIG_CB710_DEBUG is not set @@ -191,6 +194,7 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_MTD=m # CONFIG_MTD_DEBUG is not set +CONFIG_MTD_SWAP=m CONFIG_MTD_PARTITIONS=y CONFIG_MTD_AR7_PARTS=m CONFIG_MTD_CONCAT=m @@ -240,6 +244,7 @@ CONFIG_MTD_ABSENT=m # CONFIG_MTD_COMPLEX_MAPPINGS=y # CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_LATCH_ADDR is not set CONFIG_MTD_SC520CDP=m CONFIG_MTD_NETSC520=m # CONFIG_MTD_SBC_GXX is not set @@ -282,6 +287,7 @@ CONFIG_MTD_NAND=m # CONFIG_MTD_NAND_MUSEUM_IDS is not set # CONFIG_MTD_NAND_PLATFORM is not set # CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_BCH is not set # CONFIG_MTD_NAND_CAFE is not set CONFIG_MTD_NAND_IDS=m CONFIG_MTD_NAND_NANDSIM=m @@ -569,6 +575,7 @@ CONFIG_SATA_ACARD_AHCI=m CONFIG_PATA_ACPI=m CONFIG_PATA_ALI=m CONFIG_PATA_AMD=m +CONFIG_PATA_ARASAN_CF=m CONFIG_PATA_ARTOP=m CONFIG_PATA_ATIIXP=m CONFIG_PATA_CMD640_PCI=m @@ -689,6 +696,7 @@ CONFIG_DM_LOG_USERSPACE=m CONFIG_DM_MULTIPATH_QL=m CONFIG_DM_MULTIPATH_ST=m CONFIG_DM_RAID=m +CONFIG_DM_FLAKEY=m # # Fusion MPT device support @@ -759,6 +767,7 @@ CONFIG_INET_TUNNEL=m CONFIG_INET_DIAG=m CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_MULTIPATH=y CONFIG_IP_ROUTE_VERBOSE=y @@ -806,7 +815,7 @@ CONFIG_IP_VS_NQ=m CONFIG_IP_VS_FTP=m CONFIG_IP_VS_PE_SIP=m -CONFIG_IPV6=m +CONFIG_IPV6=y CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -842,11 +851,12 @@ CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NETWORK_PHY_TIMESTAMPING is not set CONFIG_NETFILTER=y CONFIG_NETFILTER_ADVANCED=y -CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK=m CONFIG_NETFILTER_NETLINK=m CONFIG_NETFILTER_NETLINK_QUEUE=m CONFIG_NETFILTER_NETLINK_LOG=m CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XT_SET=m CONFIG_NETFILTER_XT_MARK=m CONFIG_NETFILTER_XT_CONNMARK=m CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m @@ -902,6 +912,9 @@ CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m CONFIG_NETFILTER_XT_MATCH_CPU=m CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -927,6 +940,8 @@ CONFIG_NF_CONNTRACK_SIP=m CONFIG_NF_CONNTRACK_TFTP=m CONFIG_NF_CONNTRACK_IPV4=y CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_SNMP=m CONFIG_NF_NAT=m CONFIG_NF_NAT_SNMP_BASIC=m CONFIG_NF_CT_PROTO_DCCP=m @@ -1016,6 +1031,19 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_IP_SET=m +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_LIST_SET=m + # # SCTP Configuration (EXPERIMENTAL) # @@ -1077,6 +1105,10 @@ CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m CONFIG_NET_CLS=y CONFIG_NET_CLS_ACT=y CONFIG_NET_CLS_BASIC=m @@ -1421,7 +1453,10 @@ CONFIG_ADM8211=m CONFIG_ATH_COMMON=m CONFIG_ATH5K=m CONFIG_ATH5K_DEBUG=y +# CONFIG_ATH5K_TRACER is not set CONFIG_ATH9K=m +CONFIG_ATH9K_PCI=y +CONFIG_ATH9K_AHB=y # CONFIG_ATH9K_DEBUG is not set CONFIG_ATH9K_DEBUGFS=y CONFIG_ATH9K_HTC=m @@ -1479,7 +1514,13 @@ CONFIG_IWLWIFI=m CONFIG_IWLWIFI_DEBUG=y CONFIG_IWLWIFI_DEBUGFS=y CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT=y +CONFIG_IWLWIFI_DEVICE_SVTOOL=y +# CONFIG_IWL_P2P is not set CONFIG_IWLAGN=m +CONFIG_IWLWIFI_LEGACY=m +CONFIG_IWLWIFI_LEGACY_DEBUG=y +CONFIG_IWLWIFI_LEGACY_DEBUGFS=y +# CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set CONFIG_IWL4965=y CONFIG_IWL5000=y CONFIG_IWL3945=m @@ -1508,16 +1549,19 @@ CONFIG_RT2500USB=m CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y +CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800PCI=m CONFIG_RT2800PCI_RT33XX=y CONFIG_RT2800PCI_RT35XX=y +CONFIG_RT2800PCI_RT53XX=y CONFIG_RT73USB=m CONFIG_RTL8180=m CONFIG_RTL8187=m CONFIG_TMD_HERMES=m CONFIG_USB_ZD1201=m CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_USB_NET_KALMIA=m CONFIG_USB_NET_SMSC75XX=m CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1538,6 +1582,11 @@ CONFIG_WL1271_SDIO=m CONFIG_WL1271_SPI=m CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192CU=m + +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m # # Token Ring devices @@ -1597,6 +1646,8 @@ CONFIG_CAN_TSCAN1=m CONFIG_CAN_SLCAN=m CONFIG_CAN_SOFTING=m CONFIG_CAN_SOFTING_CS=m +CONFIG_CAN_C_CAN=m +CONFIG_CAN_C_CAN_PLATFORM=m # CONFIG_PCH_CAN is not set CONFIG_NETROM=m CONFIG_ROSE=m @@ -1655,9 +1706,9 @@ CONFIG_WINBOND_FIR=m # Bluetooth support # CONFIG_BT=m -CONFIG_BT_L2CAP=m +CONFIG_BT_L2CAP=y CONFIG_BT_L2CAP_EXT_FEATURES=y -CONFIG_BT_SCO=m +CONFIG_BT_SCO=y CONFIG_BT_CMTP=m CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y @@ -1689,6 +1740,7 @@ CONFIG_BT_HCIUART_LL=y CONFIG_BT_MRVL=m CONFIG_BT_MRVL_SDIO=m CONFIG_BT_ATH3K=m +CONFIG_BT_WILINK=m # # ISDN subsystem @@ -1880,12 +1932,14 @@ CONFIG_KEYBOARD_ATKBD=y # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_LM8323 is not set -# FIXME: Do we really need these keyboards enabled ? -CONFIG_KEYBOARD_ADP5588=m -CONFIG_KEYBOARD_MAX7359=m +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_QT1070 is not set # CONFIG_KEYBOARD_MCS is not set -CONFIG_KEYBOARD_OPENCORES=m -CONFIG_KEYBOARD_QT2160=m +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_QT2160 is not set # CONFIG_KEYBOARD_TCA6416 is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y @@ -1959,6 +2013,8 @@ CONFIG_TOUCHSCREEN_USB_COMPOSITE=m CONFIG_TOUCHSCREEN_W90X900=m # CONFIG_TOUCHSCREEN_BU21013 is not set CONFIG_TOUCHSCREEN_ST1232=m +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +# CONFIG_TOUCHSCREEN_MAX11801 is not set CONFIG_INPUT_MISC=y CONFIG_INPUT_PCSPKR=m @@ -1993,6 +2049,7 @@ CONFIG_SYNCLINKMP=m CONFIG_SYNCLINK_GT=m CONFIG_N_HDLC=m CONFIG_N_GSM=m +# CONFIG_TRACE_SINK is not set # CONFIG_STALDRV is not set # CONFIG_IBM_ASM is not set CONFIG_TIFM_CORE=m @@ -2041,6 +2098,7 @@ CONFIG_SERIAL_JSM=m # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_XILINX_PS_UART is not set # CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y CONFIG_DEVPTS_MULTIPLE_INSTANCES=y @@ -2113,6 +2171,8 @@ CONFIG_I2C_TINY_USB=m # CONFIG_I2C_DESIGNWARE is not set # CONFIG_I2C_XILINX is not set +CONFIG_I2C_DIOLAN_U2C=m + # # I2C Hardware Sensors Chip support # @@ -2219,6 +2279,23 @@ CONFIG_SENSORS_W83795=m # CONFIG_SENSORS_W83795_FANCTRL is not set CONFIG_SENSORS_DS620=m CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LTC4151=m +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_ADS1015=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX6642=m +CONFIG_SENSORS_ADM1275=m +CONFIG_SENSORS_UCD9000=m +CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_EMC6W201=m + +CONFIG_PMBUS=m +CONFIG_SENSORS_PMBUS=m +CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_MAX34440=m +CONFIG_SENSORS_MAX8688=m # CONFIG_HMC6352 is not set # CONFIG_BMP085 is not set @@ -2241,6 +2318,9 @@ CONFIG_W1_SLAVE_DS2433=m CONFIG_W1_SLAVE_DS2433_CRC=y CONFIG_W1_SLAVE_DS2760=m CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2408=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_BQ27000=m # # Mice @@ -2342,6 +2422,8 @@ CONFIG_RTC_DRV_WM831X=m CONFIG_RTC_DRV_BQ32K=m CONFIG_RTC_DRV_MSM6242=m CONFIG_RTC_DRV_RP5C01=m +CONFIG_RTC_DRV_EM3027=m +CONFIG_RTC_DRV_RV3029C2=m CONFIG_DTLK=m CONFIG_R3964=m @@ -2402,12 +2484,14 @@ CONFIG_HANGCHECK_TIMER=m # Multimedia devices # CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_DEV=m # CONFIG_VIDEO_ADV_DEBUG is not set CONFIG_VIDEO_HELPER_CHIPS_AUTO=y CONFIG_VIDEO_ALLOW_V4L1=y CONFIG_VIDEO_V4L1_COMPAT=y CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y # CONFIG_VIDEO_VIVI is not set # @@ -2424,11 +2508,13 @@ CONFIG_VIDEO_BT848=m CONFIG_VIDEO_BT848_DVB=y CONFIG_VIDEO_BWQCAM=m CONFIG_VIDEO_SR030PC30=m +CONFIG_VIDEO_NOON010PC30=m CONFIG_VIDEO_CAFE_CCIC=m # CONFIG_VIDEO_CPIA is not set CONFIG_VIDEO_CPIA2=m CONFIG_VIDEO_CQCAM=m CONFIG_VIDEO_CX23885=m +# CONFIG_MEDIA_ALTERA_CI is not set CONFIG_VIDEO_CX18=m CONFIG_VIDEO_CX18_ALSA=m CONFIG_VIDEO_CX88=m @@ -2473,6 +2559,7 @@ CONFIG_VIDEO_FB_IVTV=m CONFIG_VIDEO_SAA7164=m CONFIG_VIDEO_TLG2300=m # CONFIG_VIDEO_TIMBERDALE is not set +# CONFIG_VIDEO_M5MOLS is not set CONFIG_USB_VIDEO_CLASS=m CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y @@ -2484,6 +2571,7 @@ CONFIG_RADIO_GEMTEK_PCI=m CONFIG_RADIO_MAXIRADIO=m CONFIG_RADIO_MAESTRO=m CONFIG_RADIO_WL1273=m +CONFIG_RADIO_WL128X=m CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER_CUSTOMISE=y @@ -2503,6 +2591,7 @@ CONFIG_MEDIA_TUNER_MXL5007T=m CONFIG_MEDIA_TUNER_MC44S803=m CONFIG_MEDIA_TUNER_MAX2165=m CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_TDA18212=m # # Digital Video Broadcasting Devices @@ -2574,6 +2663,8 @@ CONFIG_DVB_ATBM8830=m CONFIG_DVB_TDA665x=m CONFIG_DVB_STV0299=m CONFIG_DVB_MB86A16=m +CONFIG_DVB_DRXD=m +CONFIG_DVB_CXD2820R=m # # Supported Frontend Modules @@ -2601,6 +2692,9 @@ CONFIG_DVB_DUMMY_FE=m CONFIG_DVB_FIREDTV=m CONFIG_DVB_NGENE=m CONFIG_DVB_MB86A20S=m +CONFIG_DVB_USB_TECHNISAT_USB2=m +CONFIG_DVB_DIB9000=m +CONFIG_DVB_STV0367=m # # Supported SAA7146 based PCI Adapters @@ -2675,6 +2769,12 @@ CONFIG_IR_JVC_DECODER=m CONFIG_IR_SONY_DECODER=m CONFIG_IR_RC5_SZ_DECODER=m CONFIG_IR_LIRC_CODEC=m +CONFIG_IR_IMON=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_ITE_CIR=m +CONFIG_IR_NUVOTON=m +CONFIG_IR_FINTEK=m +CONFIG_IR_REDRAT3=m CONFIG_V4L_MEM2MEM_DRIVERS=y # CONFIG_VIDEO_MEM2MEM_TESTDEV is not set @@ -2740,6 +2840,7 @@ CONFIG_FB_RIVA=m # CONFIG_FB_RIVA_I2C is not set # CONFIG_FB_S1D13XXX is not set CONFIG_FB_S3=m +CONFIG_FB_S3_DDC=y CONFIG_FB_SAVAGE=m CONFIG_FB_SAVAGE_I2C=y CONFIG_FB_SAVAGE_ACCEL=y @@ -2757,11 +2858,13 @@ CONFIG_FB_VOODOO1=m # CONFIG_FB_VT8623 is not set CONFIG_FB_EFI=y CONFIG_FB_VIA=m +CONFIG_FB_VIA_X_COMPATIBILITY=y # CONFIG_FB_VIA_DIRECT_PROCFS is not set CONFIG_FB_METRONOME=m CONFIG_FB_MB862XX=m CONFIG_FB_MB862XX_PCI_GDC=y CONFIG_FB_MB862XX_LIME=y +CONFIG_FB_MB862XX_I2C=y # CONFIG_FB_PRE_INIT_FB is not set # CONFIG_FB_TMIO is not set # CONFIG_FB_BROADSHEET is not set @@ -2872,6 +2975,7 @@ CONFIG_SND_ENS1371=m CONFIG_SND_ES1938=m CONFIG_SND_ES1968=m CONFIG_SND_ES1968_INPUT=y +CONFIG_SND_ES1968_RADIO=y CONFIG_SND_FM801=m CONFIG_SND_FM801_TEA575X_BOOL=y CONFIG_SND_CTXFI=m @@ -2929,6 +3033,7 @@ CONFIG_SND_VIRTUOSO=m CONFIG_SND_VX222=m CONFIG_SND_YMFPCI=m CONFIG_SND_ASIHPI=m +CONFIG_SND_LOLA=m # # ALSA USB devices @@ -2940,6 +3045,7 @@ CONFIG_SND_USB_CAIAQ_INPUT=y CONFIG_SND_USB_USX2Y=m CONFIG_SND_USB_US122L=m CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_6FIRE=m # # PCMCIA devices @@ -2948,6 +3054,10 @@ CONFIG_SND_PCMCIA=y CONFIG_SND_VXPOCKET=m CONFIG_SND_PDAUDIOCF=m +CONFIG_SND_FIREWIRE=y +CONFIG_SND_FIREWIRE_SPEAKERS=m +CONFIG_SND_ISIGHT=m + # # Open Sound System # @@ -2980,6 +3090,8 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set CONFIG_USB_UHCI_HCD=y +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_HCD_ISO=y # CONFIG_USB_SL811_CS is not set # CONFIG_USB_R8A66597_HCD is not set CONFIG_USB_XHCI_HCD=m @@ -3000,17 +3112,19 @@ CONFIG_USB_TMC=m # CONFIG_BLK_DEV_UB is not set CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_CYPRESS_ATACB=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_ONETOUCH=y -CONFIG_USB_STORAGE_ALAUDA=y -CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_ENE_UB6250=m # CONFIG_USB_LIBUSUAL is not set CONFIG_USB_UAS=m @@ -3064,12 +3178,10 @@ CONFIG_HID_SONY=m CONFIG_HID_SUNPLUS=m CONFIG_HID_GREENASIA=m CONFIG_HID_SMARTJOYPLUS=m -CONFIG_HID_TIVO_SLIDE=m CONFIG_HID_TOPSEED=m CONFIG_HID_THRUSTMASTER=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m -CONFIG_HID_ACRUX=m CONFIG_HID_ACRUX_FF=m CONFIG_HID_EMS_FF=m CONFIG_HID_ELECOM=m @@ -3077,6 +3189,11 @@ CONFIG_HID_UCLOGIC=m CONFIG_HID_WALTOP=m CONFIG_HID_ROCCAT_PYRA=m CONFIG_HID_ROCCAT_KONEPLUS=m +CONFIG_HID_ACRUX=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_ROCCAT_ARVO=m +CONFIG_HID_ROCCAT_KOVAPLUS=m # # USB Imaging devices @@ -3135,6 +3252,9 @@ CONFIG_USB_GSPCA_KONICA=m CONFIG_USB_GSPCA_XIRLINK_CIT=m CONFIG_USB_GSPCA_SPCA1528=m CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_NW80X=m +CONFIG_USB_GSPCA_VICAM=m +CONFIG_USB_GSPCA_KINECT=m CONFIG_USB_IBMCAM=m CONFIG_USB_KONICAWC=m @@ -3160,6 +3280,7 @@ CONFIG_SOC_CAMERA_OV9640=m CONFIG_SOC_CAMERA_OV6650=m CONFIG_SOC_CAMERA_IMX074=m CONFIG_SOC_CAMERA_OV2640=m +CONFIG_SOC_CAMERA_OV9740=m # # USB Network adaptors @@ -3188,6 +3309,7 @@ CONFIG_USB_NET_INT51X1=m CONFIG_USB_CDC_PHONET=m CONFIG_USB_IPHETH=m CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m # # USB Host-to-Host Cables @@ -3212,7 +3334,7 @@ CONFIG_USB_USS720=m # # USB Serial Converter support # -CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL=y CONFIG_USB_SERIAL_GENERIC=y CONFIG_USB_SERIAL_AIRCABLE=m CONFIG_USB_SERIAL_ARK3116=m @@ -3278,6 +3400,8 @@ CONFIG_USB_SERIAL_DEBUG=m CONFIG_USB_SERIAL_SSU100=m CONFIG_USB_SERIAL_SAMBA=m +CONFIG_USB_SERIAL_CONSOLE=y + CONFIG_USB_EZUSB=y CONFIG_USB_EMI62=m CONFIG_USB_LED=m @@ -3321,7 +3445,6 @@ CONFIG_USB_PWC_INPUT_EVDEV=y # CONFIG_USB_PWC_DEBUG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_QUICKCAM_MESSENGER is not set -CONFIG_USB_SL811_HCD=m CONFIG_USB_SISUSBVGA=m CONFIG_USB_SISUSBVGA_CON=y CONFIG_RADIO_SI470X=y @@ -3361,7 +3484,6 @@ CONFIG_PCF50633_GPIO=m # CONFIG_AB3100_CORE is not set CONFIG_INPUT_PCF50633_PMU=m CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -CONFIG_CHARGER_PCF50633=m CONFIG_RTC_DRV_PCF50633=m CONFIG_RTC_DRV_DS3232=m CONFIG_RTC_DRV_ISL12022=m @@ -3487,6 +3609,7 @@ CONFIG_PROC_KCORE=y CONFIG_PROC_VMCORE=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_DEBUG_FS=y @@ -3549,9 +3672,10 @@ CONFIG_NFS_FSCACHE=y # CONFIG_NFS_USE_LEGACY_DNS is not set # CONFIG_NFS_USE_NEW_IDMAPPER is not set # CONFIG_NFSD_DEPRECATED is not set +CONFIG_PNFS_OBJLAYOUT=m CONFIG_LOCKD=m CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m +CONFIG_EXPORTFS=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_SUNRPC_XPRT_RDMA=m @@ -3571,6 +3695,7 @@ CONFIG_CIFS_ACL=y CONFIG_CIFS_WEAK_PW_HASH=y # CONFIG_CIFS_DEBUG2 is not set CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_NFSD_EXPORT=y CONFIG_NCP_FS=m CONFIG_NCPFS_PACKET_SIGNING=y CONFIG_NCPFS_IOCTL_LOCKING=y @@ -3825,6 +3950,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=m # CONFIG_BACKLIGHT_GENERIC is not set CONFIG_BACKLIGHT_PROGEAR=m # CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set CONFIG_FB_NVIDIA_BACKLIGHT=y CONFIG_FB_RIVA_BACKLIGHT=y CONFIG_FB_RADEON_BACKLIGHT=y @@ -3857,6 +3983,7 @@ CONFIG_CGROUP_SCHED=y CONFIG_CGROUP_MEM_RES_CTLR=y CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y # XXX disabled by default, pass 'swapaccount' # CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED is not set +CONFIG_CGROUP_PERF=y CONFIG_BLK_CGROUP=y # CONFIG_DEBUG_BLK_CGROUP is not set @@ -4068,9 +4195,11 @@ CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_INTEL_SS4200=m CONFIG_LEDS_LP5521=m CONFIG_LEDS_LP5523=m +CONFIG_LEDS_LM3530=m CONFIG_DMADEVICES=y CONFIG_DMA_ENGINE=y +CONFIG_DW_DMAC=m # CONFIG_TIMB_DMA is not set CONFIG_NET_DMA=y # CONFIG_DMATEST is not set @@ -4122,13 +4251,15 @@ CONFIG_APM_POWER=m # CONFIG_BATTERY_DS2760 is not set # CONFIG_BATTERY_DS2782 is not set # CONFIG_BATTERY_BQ20Z75 is not set +# CONFIG_BATTERY_DS2780 is not set # CONFIG_CHARGER_ISP1704 is not set -CONFIG_BATTERY_PMU=m +# CONFIG_CHARGER_MAX8903 is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set # CONFIG_PDA_POWER is not set # CONFIG_CHARGER_GPIO is not set # CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_PCF50633 is not set CONFIG_AUXDISPLAY=y @@ -4172,6 +4303,8 @@ CONFIG_PM_TRACE_RTC=y CONFIG_R6040=m CONFIG_BNX2X=m +CONFIG_SCSI_BNX2X_FCOE=m + CONFIG_NOZOMI=m # CONFIG_TPS65010 is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set @@ -4199,6 +4332,7 @@ CONFIG_MEMSTICK=m CONFIG_MSPRO_BLOCK=m CONFIG_MEMSTICK_TIFM_MS=m CONFIG_MEMSTICK_JMICRON_38X=m +CONFIG_MEMSTICK_R592=m CONFIG_ACCESSIBILITY=y CONFIG_A11Y_BRAILLE_CONSOLE=y @@ -4238,7 +4372,6 @@ CONFIG_PHONET=m CONFIG_ICS932S401=m # CONFIG_C2PORT is not set -CONFIG_W1_SLAVE_BQ27000=m CONFIG_IT87_WDT=m @@ -4327,6 +4460,15 @@ CONFIG_USB_ATMEL=m # CONFIG_DX_SEP is not set # CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set # CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_RTS_PSTOR is not set +# CONFIG_DRM_PSB is not set +# CONFIG_ALTERA_STAPL is not set +# CONFIG_DVB_CXD2099 is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_BRCMSMAC is not set +# CONFIG_BRCMFMAC is not set +# CONFIG_INTEL_MEI is not set +# CONFIG_ZCACHE is not set # # Android @@ -4370,6 +4512,7 @@ CONFIG_STRIP_ASM_SYMS=y # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y CONFIG_SRCU_SYNCHRONIZE_DELAY=10 +CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -4392,6 +4535,8 @@ CONFIG_PPS_CLIENT_PARPORT=m CONFIG_PPS_GENERATOR_PARPORT=m CONFIG_NTP_PPS=y +CONFIG_PTP_1588_CLOCK=m + # CONFIG_USB_SERIAL_QUATECH2 is not set # CONFIG_VT6655 is not set CONFIG_FB_UDL=m @@ -4422,12 +4567,14 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_LOCKUP_DETECTOR=y # CONFIG_DEBUG_INFO_REDUCED is not set # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set # CONFIG_DETECT_HUNG_TASK is not set # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_ATOMIC64_SELFTEST=y CONFIG_MEMORY_FAILURE=y CONFIG_HWPOISON_INJECT=m +CONFIG_CLEANCACHE=y CONFIG_BLK_DEV_DRBD=m @@ -4448,6 +4595,7 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_IT8761E is not set # CONFIG_GPIO_MAX7300 is not set # CONFIG_UCB1400_CORE is not set +# CONFIG_TPS6105X is not set # CONFIG_RADIO_MIROPCM20 is not set # CONFIG_USB_GPIO_VBUS is not set # CONFIG_GPIO_SCH is not set @@ -4468,10 +4616,6 @@ CONFIG_IR_CORE=m CONFIG_IR_ENE=m CONFIG_IR_STREAMZAP=m CONFIG_IR_WINBOND_CIR=m -CONFIG_IR_IMON=m -CONFIG_IR_MCEUSB=m -CONFIG_IR_NUVOTON=m -CONFIG_IR_ITE_CIR=m # CONFIG_GPIO_SX150X is not set # CONFIG_MFD_STMPE is not set @@ -4493,8 +4637,28 @@ CONFIG_NFC_DEVICES=y CONFIG_PN544_NFC=m CONFIG_TARGET_CORE=m +CONFIG_LOOPBACK_TARGET=m +# CONFIG_LOOPBACK_TARGET_CDB_DEBUG is not set CONFIG_TCM_IBLOCK=m CONFIG_TCM_FILEIO=m CONFIG_TCM_PSCSI=m +CONFIG_TCM_FC=m + +CONFIG_HWSPINLOCK=m + +CONFIG_PSTORE=y + +# CONFIG_AVERAGE is not set + +# CONFIG_SIGMA is not set + +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 CONFIG_TEST_KSTRTOX=m + +CONFIG_BCMA=m +CONFIG_BCMA_HOST_PCI=y +# CONFIG_BCMA_DEBUG is not set + +# CONFIG_GOOGLE_FIRMWARE is not set +CONFIG_INTEL_MID_PTI=m diff --git a/config-ia64-generic b/config-ia64-generic index 5c864b3d0..704c704aa 100644 --- a/config-ia64-generic +++ b/config-ia64-generic @@ -140,6 +140,8 @@ CONFIG_ACPI_VIDEO=m CONFIG_ACPI_HED=m CONFIG_ACPI_EC_DEBUGFS=m CONFIG_ACPI_IPMI=m +CONFIG_ACPI_CUSTOM_METHOD=m +CONFIG_SENSORS_ACPI_POWER=m CONFIG_PM=y CONFIG_HOTPLUG_PCI=y @@ -183,6 +185,7 @@ CONFIG_PROC_VMCORE=y # CONFIG_IA64_MC_ERR_INJECT is not set CONFIG_DMIID=y +CONFIG_DMI_SYSFS=y CONFIG_SENSORS_I5K_AMB=m @@ -206,3 +209,5 @@ CONFIG_RCU_FANOUT=64 CONFIG_ACPI_POWER_METER=m CONFIG_I2C_SCMI=m + +# CONFIG_HP_ACCEL is not set diff --git a/config-nodebug b/config-nodebug index 75101842a..62650aa3a 100644 --- a/config-nodebug +++ b/config-nodebug @@ -41,6 +41,7 @@ CONFIG_CPUMASK_OFFSTACK=y # CONFIG_DEBUG_OBJECTS_SELFTEST is not set # CONFIG_DEBUG_OBJECTS_FREE is not set # CONFIG_DEBUG_OBJECTS_TIMERS is not set +# CONFIG_DEBUG_OBJECTS_RCU_HEAD is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 # CONFIG_X86_PTDUMP is not set diff --git a/config-powerpc-generic b/config-powerpc-generic index 3c8d8f058..e47c31588 100644 --- a/config-powerpc-generic +++ b/config-powerpc-generic @@ -325,6 +325,9 @@ CONFIG_PATA_MACIO=m CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_PMIC_ADP5520 is not set # CONFIG_MFD_88PM8607 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_WL1273_CORE is not set # CONFIG_XPS_USB_HCD_XILINX is not set # CONFIG_MMC_SDHCI_OF_ESDHC is not set # CONFIG_MMC_SDHCI_OF_HLWD is not set @@ -339,5 +342,16 @@ CONFIG_MPC512X_DMA=m CONFIG_KVM_GUEST=y +CONFIG_I2C_MPC=m + # CONFIG_IMA is not set # CONFIG_TCG_TPM is not set + +CONFIG_RFKILL_GPIO=m + +CONFIG_CRYPTO_DEV_FSL_CAAM=m +CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255 +CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048 +CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=m diff --git a/config-powerpc32-generic b/config-powerpc32-generic index daa06ab57..31c399e65 100644 --- a/config-powerpc32-generic +++ b/config-powerpc32-generic @@ -182,5 +182,6 @@ CONFIG_EVENT_PROFILE=y CONFIG_KVM_BOOK3S_32=m -### needs non-existant readq/writeq # CONFIG_SCSI_QLA_ISCSI is not set + +CONFIG_BATTERY_PMU=m diff --git a/config-powerpc64 b/config-powerpc64 index 2946a0686..8866a5320 100644 --- a/config-powerpc64 +++ b/config-powerpc64 @@ -184,3 +184,7 @@ CONFIG_CMM=y # CONFIG_SPARSEMEM_VMEMMAP is not set CONFIG_PSERIES_ENERGY=m + +CONFIG_PPC_ICSWX=y +CONFIG_IO_EVENT_IRQ=y +CONFIG_HW_RANDOM_AMD=m diff --git a/config-s390x b/config-s390x index 780fc9146..da9db13c1 100644 --- a/config-s390x +++ b/config-s390x @@ -233,3 +233,8 @@ CONFIG_SCHED_MC=y CONFIG_SCHED_BOOK=y CONFIG_STRICT_DEVMEM=y + +# CONFIG_WARN_DYNAMIC_STACK is not set + +CONFIG_JUMP_LABEL=y +CONFIG_CRYPTO_GHASH_S390=m diff --git a/config-x86-generic b/config-x86-generic index d6feae847..79a63a880 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -152,9 +152,11 @@ CONFIG_ACPI_POWER_METER=m CONFIG_ACPI_PROCESSOR_AGGREGATOR=m CONFIG_ACPI_HED=m CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_PCIEAER=y CONFIG_ACPI_APEI_GHES=m # CONFIG_ACPI_APEI_EINJ is not set CONFIG_ACPI_IPMI=m +CONFIG_ACPI_CUSTOM_METHOD=m # # CPUFreq processor drivers @@ -198,7 +200,6 @@ CONFIG_X86_TRAMPOLINE=y # CONFIG_NVRAM=y CONFIG_IBM_ASM=m -CONFIG_CRYPTO_AES_586=m CONFIG_CRYPTO_TWOFISH_586=m CONFIG_CRYPTO_DEV_PADLOCK=m CONFIG_CRYPTO_DEV_PADLOCK_AES=m @@ -324,6 +325,11 @@ CONFIG_TC1100_WMI=m CONFIG_HP_WMI=m # CONFIG_INTEL_SCU_IPC is not set CONFIG_DELL_WMI=m +CONFIG_DELL_WMI_AIO=m +CONFIG_ASUS_WMI=m +CONFIG_ASUS_NB_WMI=m +CONFIG_XO15_EBOOK=m +CONFIG_INTEL_OAKTRAIL=m # CONFIG_TOUCHSCREEN_INTEL_MID is not set @@ -362,6 +368,7 @@ CONFIG_LGUEST_GUEST=y CONFIG_VMI=y CONFIG_XEN=y +# CONFIG_XEN_DEBUG is not set CONFIG_XEN_MAX_DOMAIN_MEMORY=8 CONFIG_XEN_BALLOON=y CONFIG_XEN_SCRUB_PAGES=y @@ -371,13 +378,18 @@ CONFIG_XEN_FBDEV_FRONTEND=y CONFIG_XEN_KBDDEV_FRONTEND=y CONFIG_XEN_BLKDEV_FRONTEND=m CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_NETDEV_BACKEND=m +CONFIG_XEN_WDT=m +CONFIG_XEN_GRANT_DEV_ALLOC=m CONFIG_XEN_PCIDEV_FRONTEND=m CONFIG_XENFS=m CONFIG_XEN_COMPAT_XENFS=y CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=m CONFIG_XEN_DEBUG_FS=y CONFIG_XEN_PLATFORM_PCI=m CONFIG_XEN_GNTDEV=m +CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m CONFIG_MTD_ESB2ROM=m CONFIG_MTD_CK804XROM=m @@ -400,6 +412,8 @@ CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y CONFIG_MACINTOSH_DRIVERS=y CONFIG_DMIID=y +CONFIG_DMI_SYSFS=y + CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=m @@ -407,6 +421,8 @@ CONFIG_DMADEVICES=y CONFIG_INTEL_IOATDMA=m CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_FAM15H_POWER=m +CONFIG_SENSORS_ACPI_POWER=m # CONFIG_CPA_DEBUG is not set # CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set @@ -420,6 +436,9 @@ CONFIG_OLPC_OPENFIRMWARE=y CONFIG_BATTERY_OLPC=y CONFIG_MOUSE_PS2_OLPC=y +# staging +# CONFIG_FB_OLPC_DCON is not set + CONFIG_STRICT_DEVMEM=y # CONFIG_NO_BOOTMEM is not set @@ -478,6 +497,7 @@ CONFIG_SFI=y CONFIG_INPUT_WINBOND_CIR=m CONFIG_I2C_SCMI=m +CONFIG_I2C_PXA=m CONFIG_SBC_FITPC2_WATCHDOG=m CONFIG_EDAC_I3200=m CONFIG_EDAC_DECODE_MCE=m @@ -536,7 +556,8 @@ CONFIG_X86_32_IRIS=m CONFIG_TRANSPARENT_HUGEPAGE=y -CONFIG_CRYPTO_AES_NI_INTEL=m +CONFIG_CRYPTO_AES_NI_INTEL=y +CONFIG_CRYPTO_AES_586=y CONFIG_MTD_OF_PARTS=m CONFIG_MTD_PHYSMAP_OF=m @@ -544,3 +565,7 @@ CONFIG_PROC_DEVICETREE=y CONFIG_SERIAL_OF_PLATFORM=m CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m # CONFIG_MMC_SDHCI_OF is not set + +CONFIG_HP_ACCEL=m + +# CONFIG_RAPIDIO is not set diff --git a/config-x86_64-generic b/config-x86_64-generic index 0154cf1b0..d4a9a5f4e 100644 --- a/config-x86_64-generic +++ b/config-x86_64-generic @@ -98,9 +98,11 @@ CONFIG_ACPI_POWER_METER=m CONFIG_ACPI_PROCESSOR_AGGREGATOR=m CONFIG_ACPI_HED=m CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_PCIEAER=y CONFIG_ACPI_APEI_GHES=m # CONFIG_ACPI_APEI_EINJ is not set CONFIG_ACPI_IPMI=m +CONFIG_ACPI_CUSTOM_METHOD=m CONFIG_X86_PLATFORM_DEVICES=y CONFIG_ASUS_LAPTOP=m @@ -118,6 +120,12 @@ CONFIG_ACER_WMI=m CONFIG_ACERHDF=m CONFIG_HP_WMI=m CONFIG_DELL_WMI=m +CONFIG_DELL_WMI_AIO=m +CONFIG_ASUS_WMI=m +CONFIG_ASUS_NB_WMI=m +# CONFIG_XO15_EBOOK is not set +CONFIG_INTEL_OAKTRAIL=m + # CONFIG_INTEL_SCU_IPC is not set # CONFIG_TOUCHSCREEN_INTEL_MID is not set @@ -160,6 +168,7 @@ CONFIG_CRYPTO_DEV_PADLOCK_SHA=m CONFIG_CRYPTO_AES_X86_64=y CONFIG_CRYPTO_AES_NI_INTEL=y + CONFIG_CRYPTO_TWOFISH_X86_64=m CONFIG_CRYPTO_SALSA20_X86_64=m @@ -269,6 +278,8 @@ CONFIG_PROC_VMCORE=y CONFIG_CRASH=m CONFIG_DMIID=y +CONFIG_DMI_SYSFS=y + CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=m @@ -294,6 +305,7 @@ CONFIG_KVM_GUEST=y CONFIG_KVM_MMU_AUDIT=y CONFIG_XEN=y +# CONFIG_XEN_DEBUG is not set CONFIG_XEN_MAX_DOMAIN_MEMORY=32 CONFIG_XEN_BALLOON=y CONFIG_XEN_SCRUB_PAGES=y @@ -303,20 +315,27 @@ CONFIG_XEN_FBDEV_FRONTEND=y CONFIG_XEN_KBDDEV_FRONTEND=y CONFIG_XEN_BLKDEV_FRONTEND=m CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_NETDEV_BACKEND=m +CONFIG_XEN_WDT=m +CONFIG_XEN_GRANT_DEV_ALLOC=m CONFIG_XEN_PCIDEV_FRONTEND=m CONFIG_XENFS=m CONFIG_XEN_COMPAT_XENFS=y CONFIG_XEN_DEV_EVTCHN=m CONFIG_XEN_SYS_HYPERVISOR=y CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=m CONFIG_XEN_GNTDEV=m CONFIG_XEN_DEBUG_FS=y CONFIG_XEN_PLATFORM_PCI=m +CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m CONFIG_DMADEVICES=y CONFIG_INTEL_IOATDMA=m CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_FAM15H_POWER=m +CONFIG_SENSORS_ACPI_POWER=m # CONFIG_COMPAT_VDSO is not set CONFIG_PROVIDE_OHCI1394_DMA_INIT=y @@ -449,3 +468,9 @@ CONFIG_JUMP_LABEL=y CONFIG_HP_ILO=m CONFIG_TRANSPARENT_HUGEPAGE=y + +CONFIG_HP_ACCEL=m + +# CONFIG_RAPIDIO is not set + +CONFIG_BPF_JIT=y diff --git a/cx88-Fix-HVR4000-IR-keymap.patch b/cx88-Fix-HVR4000-IR-keymap.patch deleted file mode 100644 index b145cd29c..000000000 --- a/cx88-Fix-HVR4000-IR-keymap.patch +++ /dev/null @@ -1,55 +0,0 @@ -From linux-kernel-owner@vger.kernel.org Thu May 5 20:14:44 2011 -Date: Thu, 05 May 2011 17:11:08 -0700 -From: Greg KH -To: linux-kernel@vger.kernel.org, stable@kernel.org, - Greg KH -Cc: stable-review@kernel.org, torvalds@linux-foundation.org, - akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, - Jarod Wilson , - Lawrence Rust , - Linux Media Mailing List , - Lawrence Rust , - Mauro Carvalho Chehab -Subject: [patch 36/38] [media] cx88: Fix HVR4000 IR keymap -In-Reply-To: <20110506001225.GA10547@kroah.com> -X-Mailing-List: linux-kernel@vger.kernel.org - -2.6.38-stable review patch. If anyone has any objections, please let us know. - ------------------- - -From: Lawrence Rust - -[fixed in .39 in a much different way that is too big to backport to -.38 - gregkh] - -Fixes the RC key input for Nova-S plus, HVR1100, HVR3000 and HVR4000 in -the 2.6.38 kernel. - -Signed-off-by: Lawrence Rust -Acked-by: Jarod Wilson -Signed-off-by: Mauro Carvalho Chehab - ---- - drivers/media/video/cx88/cx88-input.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/media/video/cx88/cx88-input.c -+++ b/drivers/media/video/cx88/cx88-input.c -@@ -283,7 +283,7 @@ int cx88_ir_init(struct cx88_core *core, - case CX88_BOARD_PCHDTV_HD3000: - case CX88_BOARD_PCHDTV_HD5500: - case CX88_BOARD_HAUPPAUGE_IRONLY: -- ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; - ir->sampling = 1; - break; - case CX88_BOARD_WINFAST_DTV2000H: - - --- -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html -Please read the FAQ at http://www.tux.org/lkml/ - diff --git a/drm-i915-fix-pipelined-fencing.patch b/drm-i915-fix-pipelined-fencing.patch deleted file mode 100644 index b6c016c54..000000000 --- a/drm-i915-fix-pipelined-fencing.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 3b936797f5e4623ae1b80a5f0c4df30a17360bf5 Mon Sep 17 00:00:00 2001 -From: Chris Wilson -Date: Thu, 17 Mar 2011 15:23:22 +0000 -Subject: [PATCH] drm/i915: Fix pipelined fencing - -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=34584 -Cc: Andy Whitcroft -Cc: Daniel Vetter -Signed-off-by: Chris Wilson ---- - drivers/gpu/drm/i915/i915_gem.c | 46 ++++++++++++++++---------------------- - 1 files changed, 19 insertions(+), 27 deletions(-) - -diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c -index 36e66cc..10378a3 100644 ---- a/drivers/gpu/drm/i915/i915_gem.c -+++ b/drivers/gpu/drm/i915/i915_gem.c -@@ -2544,8 +2544,25 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, - reg = &dev_priv->fence_regs[obj->fence_reg]; - list_move_tail(®->lru_list, &dev_priv->mm.fence_list); - -- if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) -- pipelined = NULL; -+ if (obj->tiling_changed) { -+ ret = i915_gem_object_flush_fence(obj, -+ pipelined, -+ interruptible); -+ if (ret) -+ return ret; -+ -+ if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) -+ pipelined = NULL; -+ -+ if (pipelined) { -+ reg->setup_seqno = -+ i915_gem_next_request_seqno(dev, pipelined); -+ obj->last_fenced_seqno = reg->setup_seqno; -+ obj->last_fenced_ring = pipelined; -+ } -+ -+ goto update; -+ } - - if (!pipelined) { - if (reg->setup_seqno) { -@@ -2568,31 +2585,6 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj, - interruptible); - if (ret) - return ret; -- } else if (obj->tiling_changed) { -- if (obj->fenced_gpu_access) { -- if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { -- ret = i915_gem_flush_ring(obj->base.dev, obj->ring, -- 0, obj->base.write_domain); -- if (ret) -- return ret; -- } -- -- obj->fenced_gpu_access = false; -- } -- } -- -- if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) -- pipelined = NULL; -- BUG_ON(!pipelined && reg->setup_seqno); -- -- if (obj->tiling_changed) { -- if (pipelined) { -- reg->setup_seqno = -- i915_gem_next_request_seqno(dev, pipelined); -- obj->last_fenced_seqno = reg->setup_seqno; -- obj->last_fenced_ring = pipelined; -- } -- goto update; - } - - return 0; --- -1.5.6.5 - diff --git a/drm-intel-edp-fixes.patch b/drm-intel-edp-fixes.patch index c77ef116c..9e8c829c4 100644 --- a/drm-intel-edp-fixes.patch +++ b/drm-intel-edp-fixes.patch @@ -25,20 +25,12 @@ index 300f64b..2e3db37 100644 if (I915_READ(PCH_PP_STATUS) & PP_ON) return true; -@@ -816,7 +817,7 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp) - */ - msleep(300); +@@ -851,7 +851,7 @@ static bool ironlake_edp_panel_on (struc + I915_WRITE(PCH_PP_CONTROL, pp); + POSTING_READ(PCH_PP_CONTROL); - if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask, + if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on, 5000)) DRM_ERROR("panel on wait timed out: 0x%08x\n", I915_READ(PCH_PP_STATUS)); -@@ -922,6 +923,7 @@ static void intel_dp_prepare(struct drm_encoder *encoder) - - if (is_edp(intel_dp)) { - ironlake_edp_backlight_off(dev); -+ ironlake_edp_panel_off(dev); - ironlake_edp_panel_on(intel_dp); - if (!is_pch_edp(intel_dp)) - ironlake_edp_pll_on(encoder); diff --git a/drm-intel-eeebox-eb1007-quirk.patch b/drm-intel-eeebox-eb1007-quirk.patch deleted file mode 100644 index 9ae3604e7..000000000 --- a/drm-intel-eeebox-eb1007-quirk.patch +++ /dev/null @@ -1,36 +0,0 @@ -From ab737b006568d01204cc51368c7e2067eecb2cff Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Thu, 7 Apr 2011 13:31:57 +0200 -Subject: [PATCH] drm/i915: Add a no lvds quirk for the Asus EeeBox PC EB1007 - -I found this while figuring out why gnome-shell would not run on my -Asus EeeBox PC EB1007. As a standalone "pc" this device cleary does not have -an internal panel, yet it claims it does. Add a quirk to fix this. - -Signed-off-by: Hans de Goede ---- - drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ - 1 files changed, 8 insertions(+), 0 deletions(-) - -diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c -index a562bd2..954822a 100644 ---- a/drivers/gpu/drm/i915/intel_lvds.c -+++ b/drivers/gpu/drm/i915/intel_lvds.c -@@ -724,6 +724,14 @@ static const struct dmi_system_id intel_no_lvds[] = { - DMI_MATCH(DMI_PRODUCT_NAME, "U800"), - }, - }, -+ { -+ .callback = intel_no_lvds_dmi_callback, -+ .ident = "Asus EeeBox PC EB1007", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), -+ }, -+ }, - - { } /* terminating entry */ - }; --- -1.7.4.2 - diff --git a/drm-intel-restore-mode.patch b/drm-intel-restore-mode.patch deleted file mode 100644 index b394ca00d..000000000 --- a/drm-intel-restore-mode.patch +++ /dev/null @@ -1,128 +0,0 @@ -From e8e7a2b8ccfdae0d4cb6bd25824bbedcd42da316 Mon Sep 17 00:00:00 2001 -From: Dave Airlie -Date: Thu, 21 Apr 2011 22:18:32 +0100 -Subject: [PATCH] drm/i915: restore only the mode of this driver on lastclose (v2) - -i915 calls the panic handler function on last close to reset the modes, -however this is a really bad idea for multi-gpu machines, esp shareable -gpus machines. So add a new entry point for the driver to just restore -its own fbcon mode. - -v2: move code into fb helper, fix panic code to block mode change on -powered off GPUs. - -[airlied: this hits drm core and I wrote it and it was reviewed on intel-gfx - so really I signed it off twice ;-).] -Signed-off-by: Chris Wilson -Signed-off-by: Dave Airlie ---- - drivers/gpu/drm/drm_fb_helper.c | 27 ++++++++++++++++++++------- - drivers/gpu/drm/i915/i915_dma.c | 2 +- - drivers/gpu/drm/i915/intel_drv.h | 1 + - drivers/gpu/drm/i915/intel_fb.c | 10 ++++++++++ - include/drm/drm_fb_helper.h | 1 + - 5 files changed, 33 insertions(+), 8 deletions(-) - -diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c -index 9507204..11d7a72 100644 ---- a/drivers/gpu/drm/drm_fb_helper.c -+++ b/drivers/gpu/drm/drm_fb_helper.c -@@ -342,9 +342,22 @@ int drm_fb_helper_debug_leave(struct fb_info *info) - } - EXPORT_SYMBOL(drm_fb_helper_debug_leave); - -+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) -+{ -+ bool error = false; -+ int i, ret; -+ for (i = 0; i < fb_helper->crtc_count; i++) { -+ struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; -+ ret = drm_crtc_helper_set_config(mode_set); -+ if (ret) -+ error = true; -+ } -+ return error; -+} -+EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode); -+ - bool drm_fb_helper_force_kernel_mode(void) - { -- int i = 0; - bool ret, error = false; - struct drm_fb_helper *helper; - -@@ -352,12 +365,12 @@ bool drm_fb_helper_force_kernel_mode(void) - return false; - - list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { -- for (i = 0; i < helper->crtc_count; i++) { -- struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; -- ret = drm_crtc_helper_set_config(mode_set); -- if (ret) -- error = true; -- } -+ if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF) -+ continue; -+ -+ ret = drm_fb_helper_restore_fbdev_mode(helper); -+ if (ret) -+ error = true; - } - return error; - } -diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c -index 7273037..12876f2 100644 ---- a/drivers/gpu/drm/i915/i915_dma.c -+++ b/drivers/gpu/drm/i915/i915_dma.c -@@ -2207,7 +2207,7 @@ void i915_driver_lastclose(struct drm_device * dev) - drm_i915_private_t *dev_priv = dev->dev_private; - - if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { -- drm_fb_helper_restore(); -+ intel_fb_restore_mode(dev); - vga_switcheroo_process_delayed_switch(); - return; - } -diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h -index f5b0d83..1d20712 100644 ---- a/drivers/gpu/drm/i915/intel_drv.h -+++ b/drivers/gpu/drm/i915/intel_drv.h -@@ -338,4 +338,5 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data, - struct drm_file *file_priv); - - extern void intel_fb_output_poll_changed(struct drm_device *dev); -+extern void intel_fb_restore_mode(struct drm_device *dev); - #endif /* __INTEL_DRV_H__ */ -diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c -index 5127827..ec49bae 100644 ---- a/drivers/gpu/drm/i915/intel_fb.c -+++ b/drivers/gpu/drm/i915/intel_fb.c -@@ -264,3 +264,13 @@ void intel_fb_output_poll_changed(struct drm_device *dev) - drm_i915_private_t *dev_priv = dev->dev_private; - drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); - } -+ -+void intel_fb_restore_mode(struct drm_device *dev) -+{ -+ int ret; -+ drm_i915_private_t *dev_priv = dev->dev_private; -+ -+ ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper); -+ if (ret) -+ DRM_DEBUG("failed to restore crtc mode\n"); -+} -diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h -index f22e7fe..ade09d7 100644 ---- a/include/drm/drm_fb_helper.h -+++ b/include/drm/drm_fb_helper.h -@@ -118,6 +118,7 @@ int drm_fb_helper_setcolreg(unsigned regno, - unsigned transp, - struct fb_info *info); - -+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper); - void drm_fb_helper_restore(void); - void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, - uint32_t fb_width, uint32_t fb_height); --- -1.7.1 - diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 7a703e897..e69de29bb 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,6777 +0,0 @@ -diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c -index 6bdab89..729d5fd 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bios.c -+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c -@@ -269,7 +269,7 @@ struct init_tbl_entry { - int (*handler)(struct nvbios *, uint16_t, struct init_exec *); - }; - --static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *); -+static int parse_init_table(struct nvbios *, uint16_t, struct init_exec *); - - #define MACRO_INDEX_SIZE 2 - #define MACRO_SIZE 8 -@@ -282,7 +282,7 @@ static void still_alive(void) - { - #if 0 - sync(); -- msleep(2); -+ mdelay(2); - #endif - } - -@@ -1904,7 +1904,7 @@ init_condition_time(struct nvbios *bios, uint16_t offset, - BIOSLOG(bios, "0x%04X: " - "Condition not met, sleeping for 20ms\n", - offset); -- msleep(20); -+ mdelay(20); - } - } - -@@ -1938,7 +1938,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n", - offset, time); - -- msleep(time); -+ mdelay(time); - - return 3; - } -@@ -2011,6 +2011,27 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - } - - static int -+init_jump(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) -+{ -+ /* -+ * INIT_JUMP opcode: 0x5C ('\') -+ * -+ * offset (8 bit): opcode -+ * offset + 1 (16 bit): offset (in bios) -+ * -+ * Continue execution of init table from 'offset' -+ */ -+ -+ uint16_t jmp_offset = ROM16(bios->data[offset + 1]); -+ -+ if (!iexec->execute) -+ return 3; -+ -+ BIOSLOG(bios, "0x%04X: Jump to 0x%04X\n", offset, jmp_offset); -+ return jmp_offset - offset; -+} -+ -+static int - init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - { - /* -@@ -2962,7 +2983,7 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - if (time < 1000) - udelay(time); - else -- msleep((time + 900) / 1000); -+ mdelay((time + 900) / 1000); - - return 3; - } -@@ -3659,6 +3680,7 @@ static struct init_tbl_entry itbl_entry[] = { - { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, - /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ - { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, -+ { "INIT_JUMP" , 0x5C, init_jump }, - { "INIT_I2C_IF" , 0x5E, init_i2c_if }, - { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, - { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, -@@ -3700,8 +3722,7 @@ static struct init_tbl_entry itbl_entry[] = { - #define MAX_TABLE_OPS 1000 - - static int --parse_init_table(struct nvbios *bios, unsigned int offset, -- struct init_exec *iexec) -+parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - { - /* - * Parses all commands in an init table. -@@ -3856,7 +3877,7 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr - - if (script == LVDS_PANEL_OFF) { - /* off-on delay in ms */ -- msleep(ROM16(bios->data[bios->fp.xlated_entry + 7])); -+ mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7])); - } - #ifdef __powerpc__ - /* Powerbook specific quirks */ -@@ -5028,11 +5049,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims - pll_lim->vco1.max_n = record[11]; - pll_lim->min_p = record[12]; - pll_lim->max_p = record[13]; -- /* where did this go to?? */ -- if ((entry[0] & 0xf0) == 0x80) -- pll_lim->refclk = 27000; -- else -- pll_lim->refclk = 100000; -+ pll_lim->refclk = ROM16(entry[9]) * 1000; - } - - /* -@@ -5950,6 +5967,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) - } - } - -+static const u8 hpd_gpio[16] = { -+ 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, -+}; -+ - static void - parse_dcb_connector_table(struct nvbios *bios) - { -@@ -5986,23 +6008,9 @@ parse_dcb_connector_table(struct nvbios *bios) - - cte->type = (cte->entry & 0x000000ff) >> 0; - cte->index2 = (cte->entry & 0x00000f00) >> 8; -- switch (cte->entry & 0x00033000) { -- case 0x00001000: -- cte->gpio_tag = 0x07; -- break; -- case 0x00002000: -- cte->gpio_tag = 0x08; -- break; -- case 0x00010000: -- cte->gpio_tag = 0x51; -- break; -- case 0x00020000: -- cte->gpio_tag = 0x52; -- break; -- default: -- cte->gpio_tag = 0xff; -- break; -- } -+ -+ cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12); -+ cte->gpio_tag = hpd_gpio[cte->gpio_tag]; - - if (cte->type == 0xff) - continue; -@@ -6023,6 +6031,7 @@ parse_dcb_connector_table(struct nvbios *bios) - case DCB_CONNECTOR_DVI_I: - case DCB_CONNECTOR_DVI_D: - case DCB_CONNECTOR_LVDS: -+ case DCB_CONNECTOR_LVDS_SPWG: - case DCB_CONNECTOR_DP: - case DCB_CONNECTOR_eDP: - case DCB_CONNECTOR_HDMI_0: -@@ -6342,6 +6351,32 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) - } - } - -+ /* XFX GT-240X-YA -+ * -+ * So many things wrong here, replace the entire encoder table.. -+ */ -+ if (nv_match_device(dev, 0x0ca3, 0x1682, 0x3003)) { -+ if (idx == 0) { -+ *conn = 0x02001300; /* VGA, connector 1 */ -+ *conf = 0x00000028; -+ } else -+ if (idx == 1) { -+ *conn = 0x01010312; /* DVI, connector 0 */ -+ *conf = 0x00020030; -+ } else -+ if (idx == 2) { -+ *conn = 0x01010310; /* VGA, connector 0 */ -+ *conf = 0x00000028; -+ } else -+ if (idx == 3) { -+ *conn = 0x02022362; /* HDMI, connector 2 */ -+ *conf = 0x00020010; -+ } else { -+ *conn = 0x0000000e; /* EOL */ -+ *conf = 0x00000000; -+ } -+ } -+ - return true; - } - -@@ -6702,11 +6737,11 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, - struct nvbios *bios = &dev_priv->vbios; - struct init_exec iexec = { true, false }; - -- mutex_lock(&bios->lock); -+ spin_lock_bh(&bios->lock); - bios->display.output = dcbent; - parse_init_table(bios, table, &iexec); - bios->display.output = NULL; -- mutex_unlock(&bios->lock); -+ spin_unlock_bh(&bios->lock); - } - - static bool NVInitVBIOS(struct drm_device *dev) -@@ -6715,7 +6750,7 @@ static bool NVInitVBIOS(struct drm_device *dev) - struct nvbios *bios = &dev_priv->vbios; - - memset(bios, 0, sizeof(struct nvbios)); -- mutex_init(&bios->lock); -+ spin_lock_init(&bios->lock); - bios->dev = dev; - - if (!NVShadowVBIOS(dev, bios->data)) -diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h -index 50a648e..050c314 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bios.h -+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h -@@ -82,6 +82,7 @@ enum dcb_connector_type { - DCB_CONNECTOR_DVI_I = 0x30, - DCB_CONNECTOR_DVI_D = 0x31, - DCB_CONNECTOR_LVDS = 0x40, -+ DCB_CONNECTOR_LVDS_SPWG = 0x41, - DCB_CONNECTOR_DP = 0x46, - DCB_CONNECTOR_eDP = 0x47, - DCB_CONNECTOR_HDMI_0 = 0x60, -@@ -251,7 +252,7 @@ struct nvbios { - uint8_t digital_min_front_porch; - bool fp_no_ddc; - -- struct mutex lock; -+ spinlock_t lock; - - uint8_t data[NV_PROM_SIZE]; - unsigned int length; -diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c -index a521840..2ad49cb 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_bo.c -+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c -@@ -57,8 +57,8 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) - } - - static void --nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, -- int *page_shift) -+nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, -+ int *align, int *size, int *page_shift) - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); - -@@ -83,7 +83,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, - } - } else { - if (likely(dev_priv->chan_vm)) { -- if (*size > 256 * 1024) -+ if (!(flags & TTM_PL_FLAG_TT) && *size > 256 * 1024) - *page_shift = dev_priv->chan_vm->lpg_shift; - else - *page_shift = dev_priv->chan_vm->spg_shift; -@@ -101,8 +101,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, - int - nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, - int size, int align, uint32_t flags, uint32_t tile_mode, -- uint32_t tile_flags, bool no_vm, bool mappable, -- struct nouveau_bo **pnvbo) -+ uint32_t tile_flags, struct nouveau_bo **pnvbo) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *nvbo; -@@ -113,16 +112,14 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, - return -ENOMEM; - INIT_LIST_HEAD(&nvbo->head); - INIT_LIST_HEAD(&nvbo->entry); -- nvbo->mappable = mappable; -- nvbo->no_vm = no_vm; - nvbo->tile_mode = tile_mode; - nvbo->tile_flags = tile_flags; - nvbo->bo.bdev = &dev_priv->ttm.bdev; - -- nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift); -+ nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift); - align >>= PAGE_SHIFT; - -- if (!nvbo->no_vm && dev_priv->chan_vm) { -+ if (dev_priv->chan_vm) { - ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, - NV_MEM_ACCESS_RW, &nvbo->vma); - if (ret) { -@@ -144,11 +141,8 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, - } - nvbo->channel = NULL; - -- if (nvbo->vma.node) { -- if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) -- nvbo->bo.offset = nvbo->vma.offset; -- } -- -+ if (nvbo->vma.node) -+ nvbo->bo.offset = nvbo->vma.offset; - *pnvbo = nvbo; - return 0; - } -@@ -318,11 +312,8 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible, - if (ret) - return ret; - -- if (nvbo->vma.node) { -- if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) -- nvbo->bo.offset = nvbo->vma.offset; -- } -- -+ if (nvbo->vma.node) -+ nvbo->bo.offset = nvbo->vma.offset; - return 0; - } - -@@ -385,7 +376,8 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) - case NOUVEAU_GART_AGP: - return ttm_agp_backend_init(bdev, dev->agp->bridge); - #endif -- case NOUVEAU_GART_SGDMA: -+ case NOUVEAU_GART_PDMA: -+ case NOUVEAU_GART_HW: - return nouveau_sgdma_init_ttm(dev); - default: - NV_ERROR(dev, "Unknown GART type %d\n", -@@ -431,7 +423,10 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - man->default_caching = TTM_PL_FLAG_WC; - break; - case TTM_PL_TT: -- man->func = &ttm_bo_manager_func; -+ if (dev_priv->card_type >= NV_50) -+ man->func = &nouveau_gart_manager; -+ else -+ man->func = &ttm_bo_manager_func; - switch (dev_priv->gart_info.type) { - case NOUVEAU_GART_AGP: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; -@@ -439,7 +434,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, - TTM_PL_FLAG_WC; - man->default_caching = TTM_PL_FLAG_WC; - break; -- case NOUVEAU_GART_SGDMA: -+ case NOUVEAU_GART_PDMA: -+ case NOUVEAU_GART_HW: - man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | - TTM_MEMTYPE_FLAG_CMA; - man->available_caching = TTM_PL_MASK_CACHING; -@@ -501,45 +497,22 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, - return ret; - } - --static inline uint32_t --nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, -- struct nouveau_channel *chan, struct ttm_mem_reg *mem) --{ -- struct nouveau_bo *nvbo = nouveau_bo(bo); -- -- if (nvbo->no_vm) { -- if (mem->mem_type == TTM_PL_TT) -- return NvDmaGART; -- return NvDmaVRAM; -- } -- -- if (mem->mem_type == TTM_PL_TT) -- return chan->gart_handle; -- return chan->vram_handle; --} -- - static int - nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) - { -- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -+ struct nouveau_mem *old_node = old_mem->mm_node; -+ struct nouveau_mem *new_node = new_mem->mm_node; - struct nouveau_bo *nvbo = nouveau_bo(bo); -- u64 src_offset = old_mem->start << PAGE_SHIFT; -- u64 dst_offset = new_mem->start << PAGE_SHIFT; - u32 page_count = new_mem->num_pages; -+ u64 src_offset, dst_offset; - int ret; - -- if (!nvbo->no_vm) { -- if (old_mem->mem_type == TTM_PL_VRAM) -- src_offset = nvbo->vma.offset; -- else -- src_offset += dev_priv->gart_info.aper_base; -- -- if (new_mem->mem_type == TTM_PL_VRAM) -- dst_offset = nvbo->vma.offset; -- else -- dst_offset += dev_priv->gart_info.aper_base; -- } -+ src_offset = old_node->tmp_vma.offset; -+ if (new_node->tmp_vma.node) -+ dst_offset = new_node->tmp_vma.offset; -+ else -+ dst_offset = nvbo->vma.offset; - - page_count = new_mem->num_pages; - while (page_count) { -@@ -574,33 +547,18 @@ static int - nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) - { -- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -+ struct nouveau_mem *old_node = old_mem->mm_node; -+ struct nouveau_mem *new_node = new_mem->mm_node; - struct nouveau_bo *nvbo = nouveau_bo(bo); - u64 length = (new_mem->num_pages << PAGE_SHIFT); - u64 src_offset, dst_offset; - int ret; - -- src_offset = old_mem->start << PAGE_SHIFT; -- dst_offset = new_mem->start << PAGE_SHIFT; -- if (!nvbo->no_vm) { -- if (old_mem->mem_type == TTM_PL_VRAM) -- src_offset = nvbo->vma.offset; -- else -- src_offset += dev_priv->gart_info.aper_base; -- -- if (new_mem->mem_type == TTM_PL_VRAM) -- dst_offset = nvbo->vma.offset; -- else -- dst_offset += dev_priv->gart_info.aper_base; -- } -- -- ret = RING_SPACE(chan, 3); -- if (ret) -- return ret; -- -- BEGIN_RING(chan, NvSubM2MF, 0x0184, 2); -- OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); -- OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); -+ src_offset = old_node->tmp_vma.offset; -+ if (new_node->tmp_vma.node) -+ dst_offset = new_node->tmp_vma.offset; -+ else -+ dst_offset = nvbo->vma.offset; - - while (length) { - u32 amount, stride, height; -@@ -681,6 +639,15 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - return 0; - } - -+static inline uint32_t -+nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, -+ struct nouveau_channel *chan, struct ttm_mem_reg *mem) -+{ -+ if (mem->mem_type == TTM_PL_TT) -+ return chan->gart_handle; -+ return chan->vram_handle; -+} -+ - static int - nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) -@@ -734,15 +701,43 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct nouveau_bo *nvbo = nouveau_bo(bo); -+ struct ttm_mem_reg *old_mem = &bo->mem; - struct nouveau_channel *chan; - int ret; - - chan = nvbo->channel; -- if (!chan || nvbo->no_vm) { -+ if (!chan) { - chan = dev_priv->channel; - mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); - } - -+ /* create temporary vma for old memory, this will get cleaned -+ * up after ttm destroys the ttm_mem_reg -+ */ -+ if (dev_priv->card_type >= NV_50) { -+ struct nouveau_mem *node = old_mem->mm_node; -+ if (!node->tmp_vma.node) { -+ u32 page_shift = nvbo->vma.node->type; -+ if (old_mem->mem_type == TTM_PL_TT) -+ page_shift = nvbo->vma.vm->spg_shift; -+ -+ ret = nouveau_vm_get(chan->vm, -+ old_mem->num_pages << PAGE_SHIFT, -+ page_shift, NV_MEM_ACCESS_RO, -+ &node->tmp_vma); -+ if (ret) -+ goto out; -+ } -+ -+ if (old_mem->mem_type == TTM_PL_VRAM) -+ nouveau_vm_map(&node->tmp_vma, node); -+ else { -+ nouveau_vm_map_sg(&node->tmp_vma, 0, -+ old_mem->num_pages << PAGE_SHIFT, -+ node, node->pages); -+ } -+ } -+ - if (dev_priv->card_type < NV_50) - ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); - else -@@ -756,6 +751,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, - no_wait_gpu, new_mem); - } - -+out: - if (chan == dev_priv->channel) - mutex_unlock(&chan->mutex); - return ret; -@@ -766,6 +762,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, - bool no_wait_reserve, bool no_wait_gpu, - struct ttm_mem_reg *new_mem) - { -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; - struct ttm_placement placement; - struct ttm_mem_reg tmp_mem; -@@ -785,7 +782,23 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, - if (ret) - goto out; - -+ if (dev_priv->card_type >= NV_50) { -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ struct nouveau_mem *node = tmp_mem.mm_node; -+ struct nouveau_vma *vma = &nvbo->vma; -+ if (vma->node->type != vma->vm->spg_shift) -+ vma = &node->tmp_vma; -+ nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT, -+ node, node->pages); -+ } -+ - ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem); -+ -+ if (dev_priv->card_type >= NV_50) { -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ nouveau_vm_unmap(&nvbo->vma); -+ } -+ - if (ret) - goto out; - -@@ -828,6 +841,36 @@ out: - return ret; - } - -+static void -+nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -+ struct nouveau_mem *node = new_mem->mm_node; -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ struct nouveau_vma *vma = &nvbo->vma; -+ struct nouveau_vm *vm = vma->vm; -+ -+ if (dev_priv->card_type < NV_50) -+ return; -+ -+ switch (new_mem->mem_type) { -+ case TTM_PL_VRAM: -+ nouveau_vm_map(vma, node); -+ break; -+ case TTM_PL_TT: -+ if (vma->node->type != vm->spg_shift) { -+ nouveau_vm_unmap(vma); -+ vma = &node->tmp_vma; -+ } -+ nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT, -+ node, node->pages); -+ break; -+ default: -+ nouveau_vm_unmap(&nvbo->vma); -+ break; -+ } -+} -+ - static int - nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, - struct nouveau_tile_reg **new_tile) -@@ -835,19 +878,13 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct drm_device *dev = dev_priv->dev; - struct nouveau_bo *nvbo = nouveau_bo(bo); -- uint64_t offset; -+ u64 offset = new_mem->start << PAGE_SHIFT; - -- if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { -- /* Nothing to do. */ -- *new_tile = NULL; -+ *new_tile = NULL; -+ if (new_mem->mem_type != TTM_PL_VRAM) - return 0; -- } -- -- offset = new_mem->start << PAGE_SHIFT; - -- if (dev_priv->chan_vm) { -- nouveau_vm_map(&nvbo->vma, new_mem->mm_node); -- } else if (dev_priv->card_type >= NV_10) { -+ if (dev_priv->card_type >= NV_10) { - *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, - nvbo->tile_mode, - nvbo->tile_flags); -@@ -864,11 +901,8 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct drm_device *dev = dev_priv->dev; - -- if (dev_priv->card_type >= NV_10 && -- dev_priv->card_type < NV_50) { -- nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); -- *old_tile = new_tile; -- } -+ nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); -+ *old_tile = new_tile; - } - - static int -@@ -882,9 +916,11 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, - struct nouveau_tile_reg *new_tile = NULL; - int ret = 0; - -- ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); -- if (ret) -- return ret; -+ if (dev_priv->card_type < NV_50) { -+ ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); -+ if (ret) -+ return ret; -+ } - - /* Fake bo copy. */ - if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { -@@ -915,10 +951,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, - ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); - - out: -- if (ret) -- nouveau_bo_vm_cleanup(bo, NULL, &new_tile); -- else -- nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); -+ if (dev_priv->card_type < NV_50) { -+ if (ret) -+ nouveau_bo_vm_cleanup(bo, NULL, &new_tile); -+ else -+ nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); -+ } - - return ret; - } -@@ -959,7 +997,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) - break; - case TTM_PL_VRAM: - { -- struct nouveau_vram *vram = mem->mm_node; -+ struct nouveau_mem *node = mem->mm_node; - u8 page_shift; - - if (!dev_priv->bar1_vm) { -@@ -970,23 +1008,23 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) - } - - if (dev_priv->card_type == NV_C0) -- page_shift = vram->page_shift; -+ page_shift = node->page_shift; - else - page_shift = 12; - - ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, - page_shift, NV_MEM_ACCESS_RW, -- &vram->bar_vma); -+ &node->bar_vma); - if (ret) - return ret; - -- nouveau_vm_map(&vram->bar_vma, vram); -+ nouveau_vm_map(&node->bar_vma, node); - if (ret) { -- nouveau_vm_put(&vram->bar_vma); -+ nouveau_vm_put(&node->bar_vma); - return ret; - } - -- mem->bus.offset = vram->bar_vma.offset; -+ mem->bus.offset = node->bar_vma.offset; - if (dev_priv->card_type == NV_50) /*XXX*/ - mem->bus.offset -= 0x0020000000ULL; - mem->bus.base = pci_resource_start(dev->pdev, 1); -@@ -1003,16 +1041,16 @@ static void - nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); -- struct nouveau_vram *vram = mem->mm_node; -+ struct nouveau_mem *node = mem->mm_node; - - if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) - return; - -- if (!vram->bar_vma.node) -+ if (!node->bar_vma.node) - return; - -- nouveau_vm_unmap(&vram->bar_vma); -- nouveau_vm_put(&vram->bar_vma); -+ nouveau_vm_unmap(&node->bar_vma); -+ nouveau_vm_put(&node->bar_vma); - } - - static int -@@ -1062,6 +1100,7 @@ struct ttm_bo_driver nouveau_bo_driver = { - .invalidate_caches = nouveau_bo_invalidate_caches, - .init_mem_type = nouveau_bo_init_mem_type, - .evict_flags = nouveau_bo_evict_flags, -+ .move_notify = nouveau_bo_move_ntfy, - .move = nouveau_bo_move, - .verify_access = nouveau_bo_verify_access, - .sync_obj_signaled = __nouveau_fence_signalled, -diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c -index 3960d66..3837090 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_channel.c -+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c -@@ -35,7 +35,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *pb = chan->pushbuf_bo; - struct nouveau_gpuobj *pushbuf = NULL; -- int ret; -+ int ret = 0; - - if (dev_priv->card_type >= NV_50) { - if (dev_priv->card_type < NV_C0) { -@@ -90,8 +90,7 @@ nouveau_channel_user_pushbuf_alloc(struct drm_device *dev) - else - location = TTM_PL_FLAG_TT; - -- ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false, -- true, &pushbuf); -+ ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf); - if (ret) { - NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); - return NULL; -diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c -index 390d82c..084c089 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_connector.c -+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c -@@ -438,7 +438,7 @@ nouveau_connector_set_property(struct drm_connector *connector, - } - - /* LVDS always needs gpu scaling */ -- if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS && -+ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS && - value == DRM_MODE_SCALE_NONE) - return -EINVAL; - -@@ -646,6 +646,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) - ret = get_slave_funcs(encoder)->get_modes(encoder, connector); - - if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || -+ nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG || - nv_connector->dcb->type == DCB_CONNECTOR_eDP) - ret += nouveau_connector_scaler_modes_add(connector); - -@@ -806,6 +807,7 @@ nouveau_connector_create(struct drm_device *dev, int index) - type = DRM_MODE_CONNECTOR_HDMIA; - break; - case DCB_CONNECTOR_LVDS: -+ case DCB_CONNECTOR_LVDS_SPWG: - type = DRM_MODE_CONNECTOR_LVDS; - funcs = &nouveau_connector_funcs_lvds; - break; -@@ -834,7 +836,7 @@ nouveau_connector_create(struct drm_device *dev, int index) - drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); - - /* Check if we need dithering enabled */ -- if (dcb->type == DCB_CONNECTOR_LVDS) { -+ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { - bool dummy, is_24bit = false; - - ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit); -@@ -879,7 +881,7 @@ nouveau_connector_create(struct drm_device *dev, int index) - nv_connector->use_dithering ? - DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); - -- if (dcb->type != DCB_CONNECTOR_LVDS) { -+ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) { - if (dev_priv->card_type >= NV_50) - connector->polled = DRM_CONNECTOR_POLL_HPD; - else -diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c -index 505c6bf..764c15d 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_display.c -+++ b/drivers/gpu/drm/nouveau/nouveau_display.c -@@ -32,6 +32,7 @@ - #include "nouveau_hw.h" - #include "nouveau_crtc.h" - #include "nouveau_dma.h" -+#include "nv50_display.h" - - static void - nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) -@@ -61,18 +62,59 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { - }; - - int --nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, -- struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo) -+nouveau_framebuffer_init(struct drm_device *dev, -+ struct nouveau_framebuffer *nv_fb, -+ struct drm_mode_fb_cmd *mode_cmd, -+ struct nouveau_bo *nvbo) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct drm_framebuffer *fb = &nv_fb->base; - int ret; - -- ret = drm_framebuffer_init(dev, &nouveau_fb->base, &nouveau_framebuffer_funcs); -+ ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs); - if (ret) { - return ret; - } - -- drm_helper_mode_fill_fb_struct(&nouveau_fb->base, mode_cmd); -- nouveau_fb->nvbo = nvbo; -+ drm_helper_mode_fill_fb_struct(fb, mode_cmd); -+ nv_fb->nvbo = nvbo; -+ -+ if (dev_priv->card_type >= NV_50) { -+ u32 tile_flags = nouveau_bo_tile_layout(nvbo); -+ if (tile_flags == 0x7a00 || -+ tile_flags == 0xfe00) -+ nv_fb->r_dma = NvEvoFB32; -+ else -+ if (tile_flags == 0x7000) -+ nv_fb->r_dma = NvEvoFB16; -+ else -+ nv_fb->r_dma = NvEvoVRAM_LP; -+ -+ switch (fb->depth) { -+ case 8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break; -+ case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break; -+ case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break; -+ case 24: -+ case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; -+ case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; -+ default: -+ NV_ERROR(dev, "unknown depth %d\n", fb->depth); -+ return -EINVAL; -+ } -+ -+ if (dev_priv->chipset == 0x50) -+ nv_fb->r_format |= (tile_flags << 8); -+ -+ if (!tile_flags) -+ nv_fb->r_pitch = 0x00100000 | fb->pitch; -+ else { -+ u32 mode = nvbo->tile_mode; -+ if (dev_priv->card_type >= NV_C0) -+ mode >>= 4; -+ nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode; -+ } -+ } -+ - return 0; - } - -@@ -182,6 +224,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, - struct nouveau_page_flip_state *s, - struct nouveau_fence **pfence) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; - unsigned long flags; - int ret; -@@ -201,9 +244,12 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, - if (ret) - goto fail; - -- BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); -- OUT_RING(chan, 0); -- FIRE_RING(chan); -+ if (dev_priv->card_type < NV_C0) -+ BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); -+ else -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1); -+ OUT_RING (chan, 0); -+ FIRE_RING (chan); - - ret = nouveau_fence_new(chan, pfence, true); - if (ret) -@@ -244,7 +290,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - - /* Initialize a page flip struct */ - *s = (struct nouveau_page_flip_state) -- { { }, s->event, nouveau_crtc(crtc)->index, -+ { { }, event, nouveau_crtc(crtc)->index, - fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, - new_bo->bo.offset }; - -@@ -255,6 +301,14 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - mutex_lock(&chan->mutex); - - /* Emit a page flip */ -+ if (dev_priv->card_type >= NV_50) { -+ ret = nv50_display_flip_next(crtc, fb, chan); -+ if (ret) { -+ nouveau_channel_put(&chan); -+ goto fail_unreserve; -+ } -+ } -+ - ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); - nouveau_channel_put(&chan); - if (ret) -@@ -305,7 +359,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, - } - - list_del(&s->head); -- *ps = *s; -+ if (ps) -+ *ps = *s; - kfree(s); - - spin_unlock_irqrestore(&dev->event_lock, flags); -diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c -index b368ed7..568caed 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_dma.c -+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c -@@ -83,7 +83,7 @@ nouveau_dma_init(struct nouveau_channel *chan) - return ret; - - /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ -- ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfd0, 0x1000, -+ ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000, - &chan->m2mf_ntfy); - if (ret) - return ret; -@@ -97,13 +97,15 @@ nouveau_dma_init(struct nouveau_channel *chan) - OUT_RING(chan, 0); - - /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */ -- ret = RING_SPACE(chan, 4); -+ ret = RING_SPACE(chan, 6); - if (ret) - return ret; - BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); -- OUT_RING(chan, NvM2MF); -- BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); -- OUT_RING(chan, NvNotify0); -+ OUT_RING (chan, NvM2MF); -+ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3); -+ OUT_RING (chan, NvNotify0); -+ OUT_RING (chan, chan->vram_handle); -+ OUT_RING (chan, chan->gart_handle); - - /* Sit back and pray the channel works.. */ - FIRE_RING(chan); -diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h -index c36f176..23d4edf 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_dma.h -+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h -@@ -61,8 +61,6 @@ enum { - NvM2MF = 0x80000001, - NvDmaFB = 0x80000002, - NvDmaTT = 0x80000003, -- NvDmaVRAM = 0x80000004, -- NvDmaGART = 0x80000005, - NvNotify0 = 0x80000006, - Nv2D = 0x80000007, - NvCtxSurf2D = 0x80000008, -@@ -73,12 +71,15 @@ enum { - NvImageBlit = 0x8000000d, - NvSw = 0x8000000e, - NvSema = 0x8000000f, -+ NvEvoSema0 = 0x80000010, -+ NvEvoSema1 = 0x80000011, - - /* G80+ display objects */ - NvEvoVRAM = 0x01000000, - NvEvoFB16 = 0x01000001, - NvEvoFB32 = 0x01000002, -- NvEvoVRAM_LP = 0x01000003 -+ NvEvoVRAM_LP = 0x01000003, -+ NvEvoSync = 0xcafe0000 - }; - - #define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 -diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c -index 38d5995..7beb82a 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_dp.c -+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c -@@ -175,7 +175,6 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) - { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; -- struct bit_displayport_encoder_table_entry *dpse; - struct bit_displayport_encoder_table *dpe; - int ret, i, dpe_headerlen, vs = 0, pre = 0; - uint8_t request[2]; -@@ -183,7 +182,6 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) - dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); - if (!dpe) - return false; -- dpse = (void *)((char *)dpe + dpe_headerlen); - - ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2); - if (ret) -diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index 982d70b..b260c55 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_drv.h -+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -57,7 +57,7 @@ struct nouveau_fpriv { - #include "nouveau_util.h" - - struct nouveau_grctx; --struct nouveau_vram; -+struct nouveau_mem; - #include "nouveau_vm.h" - - #define MAX_NUM_DCB_ENTRIES 16 -@@ -65,13 +65,16 @@ struct nouveau_vram; - #define NOUVEAU_MAX_CHANNEL_NR 128 - #define NOUVEAU_MAX_TILE_NR 15 - --struct nouveau_vram { -+struct nouveau_mem { - struct drm_device *dev; - - struct nouveau_vma bar_vma; -+ struct nouveau_vma tmp_vma; - u8 page_shift; - -+ struct drm_mm_node *tag; - struct list_head regions; -+ dma_addr_t *pages; - u32 memtype; - u64 offset; - u64 size; -@@ -90,6 +93,7 @@ struct nouveau_tile_reg { - struct nouveau_bo { - struct ttm_buffer_object bo; - struct ttm_placement placement; -+ u32 valid_domains; - u32 placements[3]; - u32 busy_placements[3]; - struct ttm_bo_kmap_obj kmap; -@@ -104,8 +108,6 @@ struct nouveau_bo { - struct nouveau_channel *channel; - - struct nouveau_vma vma; -- bool mappable; -- bool no_vm; - - uint32_t tile_mode; - uint32_t tile_flags; -@@ -387,6 +389,7 @@ struct nouveau_pgraph_engine { - }; - - struct nouveau_display_engine { -+ void *priv; - int (*early_init)(struct drm_device *); - void (*late_takedown)(struct drm_device *); - int (*create)(struct drm_device *); -@@ -433,6 +436,7 @@ struct nouveau_pm_level { - u32 memory; - u32 shader; - u32 unk05; -+ u32 unk0a; - - u8 voltage; - u8 fanspeed; -@@ -463,6 +467,7 @@ struct nouveau_pm_memtiming { - u32 reg_100234; - u32 reg_100238; - u32 reg_10023c; -+ u32 reg_100240; - }; - - struct nouveau_pm_memtimings { -@@ -509,8 +514,8 @@ struct nouveau_crypt_engine { - struct nouveau_vram_engine { - int (*init)(struct drm_device *); - int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, -- u32 type, struct nouveau_vram **); -- void (*put)(struct drm_device *, struct nouveau_vram **); -+ u32 type, struct nouveau_mem **); -+ void (*put)(struct drm_device *, struct nouveau_mem **); - - bool (*flags_valid)(struct drm_device *, u32 tile_flags); - }; -@@ -634,6 +639,7 @@ struct drm_nouveau_private { - enum nouveau_card_type card_type; - /* exact chipset, derived from NV_PMC_BOOT_0 */ - int chipset; -+ int stepping; - int flags; - - void __iomem *mmio; -@@ -652,8 +658,6 @@ struct drm_nouveau_private { - /* interrupt handling */ - void (*irq_handler[32])(struct drm_device *); - bool msi_enabled; -- struct workqueue_struct *wq; -- struct work_struct irq_work; - - struct list_head vbl_waiting; - -@@ -681,6 +685,9 @@ struct drm_nouveau_private { - /* For PFIFO and PGRAPH. */ - spinlock_t context_switch_lock; - -+ /* VM/PRAMIN flush, legacy PRAMIN aperture */ -+ spinlock_t vm_lock; -+ - /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ - struct nouveau_ramht *ramht; - struct nouveau_gpuobj *ramfc; -@@ -691,15 +698,22 @@ struct drm_nouveau_private { - struct { - enum { - NOUVEAU_GART_NONE = 0, -- NOUVEAU_GART_AGP, -- NOUVEAU_GART_SGDMA -+ NOUVEAU_GART_AGP, /* AGP */ -+ NOUVEAU_GART_PDMA, /* paged dma object */ -+ NOUVEAU_GART_HW /* on-chip gart/vm */ - } type; - uint64_t aper_base; - uint64_t aper_size; - uint64_t aper_free; - -+ struct ttm_backend_func *func; -+ -+ struct { -+ struct page *page; -+ dma_addr_t addr; -+ } dummy; -+ - struct nouveau_gpuobj *sg_ctxdma; -- struct nouveau_vma vma; - } gart_info; - - /* nv10-nv40 tiling regions */ -@@ -740,14 +754,6 @@ struct drm_nouveau_private { - - struct backlight_device *backlight; - -- struct nouveau_channel *evo; -- u32 evo_alloc; -- struct { -- struct dcb_entry *dcb; -- u16 script; -- u32 pclk; -- } evo_irq; -- - struct { - struct dentry *channel_root; - } debugfs; -@@ -847,6 +853,7 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, - struct nouveau_tile_reg *tile, - struct nouveau_fence *fence); - extern const struct ttm_mem_type_manager_func nouveau_vram_manager; -+extern const struct ttm_mem_type_manager_func nouveau_gart_manager; - - /* nouveau_notifier.c */ - extern int nouveau_notifier_init_channel(struct nouveau_channel *); -@@ -879,17 +886,17 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan, - extern void nouveau_channel_idle(struct nouveau_channel *chan); - - /* nouveau_object.c */ --#define NVOBJ_CLASS(d,c,e) do { \ -+#define NVOBJ_CLASS(d, c, e) do { \ - int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ - if (ret) \ - return ret; \ --} while(0) -+} while (0) - --#define NVOBJ_MTHD(d,c,m,e) do { \ -+#define NVOBJ_MTHD(d, c, m, e) do { \ - int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \ - if (ret) \ - return ret; \ --} while(0) -+} while (0) - - extern int nouveau_gpuobj_early_init(struct drm_device *); - extern int nouveau_gpuobj_init(struct drm_device *); -@@ -899,7 +906,7 @@ extern void nouveau_gpuobj_resume(struct drm_device *dev); - extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); - extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, - int (*exec)(struct nouveau_channel *, -- u32 class, u32 mthd, u32 data)); -+ u32 class, u32 mthd, u32 data)); - extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); - extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); - extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, -@@ -1076,7 +1083,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); - /* nv50_fb.c */ - extern int nv50_fb_init(struct drm_device *); - extern void nv50_fb_takedown(struct drm_device *); --extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *); -+extern void nv50_fb_vm_trap(struct drm_device *, int display); - - /* nvc0_fb.c */ - extern int nvc0_fb_init(struct drm_device *); -@@ -1189,7 +1196,7 @@ extern int nv50_graph_load_context(struct nouveau_channel *); - extern int nv50_graph_unload_context(struct drm_device *); - extern int nv50_grctx_init(struct nouveau_grctx *); - extern void nv50_graph_tlb_flush(struct drm_device *dev); --extern void nv86_graph_tlb_flush(struct drm_device *dev); -+extern void nv84_graph_tlb_flush(struct drm_device *dev); - extern struct nouveau_enum nv50_data_error_names[]; - - /* nvc0_graph.c */ -@@ -1295,7 +1302,7 @@ extern struct ttm_bo_driver nouveau_bo_driver; - extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, - int size, int align, uint32_t flags, - uint32_t tile_mode, uint32_t tile_flags, -- bool no_vm, bool mappable, struct nouveau_bo **); -+ struct nouveau_bo **); - extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); - extern int nouveau_bo_unpin(struct nouveau_bo *); - extern int nouveau_bo_map(struct nouveau_bo *); -@@ -1356,9 +1363,9 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) - - /* nouveau_gem.c */ - extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, -- int size, int align, uint32_t flags, -+ int size, int align, uint32_t domain, - uint32_t tile_mode, uint32_t tile_flags, -- bool no_vm, bool mappable, struct nouveau_bo **); -+ struct nouveau_bo **); - extern int nouveau_gem_object_new(struct drm_gem_object *); - extern void nouveau_gem_object_del(struct drm_gem_object *); - extern int nouveau_gem_ioctl_new(struct drm_device *, void *, -@@ -1398,8 +1405,8 @@ bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); - /* nv50_calc. */ - int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, - int *N1, int *M1, int *N2, int *M2, int *P); --int nv50_calc_pll2(struct drm_device *, struct pll_lims *, -- int clk, int *N, int *fN, int *M, int *P); -+int nva3_calc_pll(struct drm_device *, struct pll_lims *, -+ int clk, int *N, int *fN, int *M, int *P); - - #ifndef ioread32_native - #ifdef __BIG_ENDIAN -diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h -index d432134..a3a88ad 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fb.h -+++ b/drivers/gpu/drm/nouveau/nouveau_fb.h -@@ -30,6 +30,9 @@ - struct nouveau_framebuffer { - struct drm_framebuffer base; - struct nouveau_bo *nvbo; -+ u32 r_dma; -+ u32 r_format; -+ u32 r_pitch; - }; - - static inline struct nouveau_framebuffer * -diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -index 7826be0..39aee6d 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c -+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c -@@ -296,8 +296,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, - size = mode_cmd.pitch * mode_cmd.height; - size = roundup(size, PAGE_SIZE); - -- ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, -- 0, 0x0000, false, true, &nvbo); -+ ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, -+ NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); - if (ret) { - NV_ERROR(dev, "failed to allocate framebuffer\n"); - goto out; -diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c -index 221b846..4b9f449 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_fence.c -+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c -@@ -27,13 +27,15 @@ - #include "drmP.h" - #include "drm.h" - -+#include -+#include -+ - #include "nouveau_drv.h" - #include "nouveau_ramht.h" - #include "nouveau_dma.h" - - #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) --#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \ -- nouveau_private(dev)->card_type < NV_C0) -+#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) - - struct nouveau_fence { - struct nouveau_channel *channel; -@@ -230,7 +232,8 @@ int - __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) - { - unsigned long timeout = jiffies + (3 * DRM_HZ); -- unsigned long sleep_time = jiffies + 1; -+ unsigned long sleep_time = NSEC_PER_MSEC / 1000; -+ ktime_t t; - int ret = 0; - - while (1) { -@@ -244,8 +247,13 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) - - __set_current_state(intr ? TASK_INTERRUPTIBLE - : TASK_UNINTERRUPTIBLE); -- if (lazy && time_after_eq(jiffies, sleep_time)) -- schedule_timeout(1); -+ if (lazy) { -+ t = ktime_set(0, sleep_time); -+ schedule_hrtimeout(&t, HRTIMER_MODE_REL); -+ sleep_time *= 2; -+ if (sleep_time > NSEC_PER_MSEC) -+ sleep_time = NSEC_PER_MSEC; -+ } - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; -@@ -259,11 +267,12 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) - } - - static struct nouveau_semaphore * --alloc_semaphore(struct drm_device *dev) -+semaphore_alloc(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_semaphore *sema; -- int ret; -+ int size = (dev_priv->chipset < 0x84) ? 4 : 16; -+ int ret, i; - - if (!USE_SEMA(dev)) - return NULL; -@@ -277,9 +286,9 @@ alloc_semaphore(struct drm_device *dev) - goto fail; - - spin_lock(&dev_priv->fence.lock); -- sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); -+ sema->mem = drm_mm_search_free(&dev_priv->fence.heap, size, 0, 0); - if (sema->mem) -- sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0); -+ sema->mem = drm_mm_get_block_atomic(sema->mem, size, 0); - spin_unlock(&dev_priv->fence.lock); - - if (!sema->mem) -@@ -287,7 +296,8 @@ alloc_semaphore(struct drm_device *dev) - - kref_init(&sema->ref); - sema->dev = dev; -- nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 0); -+ for (i = sema->mem->start; i < sema->mem->start + size; i += 4) -+ nouveau_bo_wr32(dev_priv->fence.bo, i / 4, 0); - - return sema; - fail: -@@ -296,7 +306,7 @@ fail: - } - - static void --free_semaphore(struct kref *ref) -+semaphore_free(struct kref *ref) - { - struct nouveau_semaphore *sema = - container_of(ref, struct nouveau_semaphore, ref); -@@ -318,61 +328,107 @@ semaphore_work(void *priv, bool signalled) - if (unlikely(!signalled)) - nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1); - -- kref_put(&sema->ref, free_semaphore); -+ kref_put(&sema->ref, semaphore_free); - } - - static int --emit_semaphore(struct nouveau_channel *chan, int method, -- struct nouveau_semaphore *sema) -+semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) - { -- struct drm_nouveau_private *dev_priv = sema->dev->dev_private; -- struct nouveau_fence *fence; -- bool smart = (dev_priv->card_type >= NV_50); -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nouveau_fence *fence = NULL; - int ret; - -- ret = RING_SPACE(chan, smart ? 8 : 4); -+ if (dev_priv->chipset < 0x84) { -+ ret = RING_SPACE(chan, 3); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); -+ OUT_RING (chan, sema->mem->start); -+ OUT_RING (chan, 1); -+ } else -+ if (dev_priv->chipset < 0xc0) { -+ struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -+ u64 offset = vma->offset + sema->mem->start; -+ -+ ret = RING_SPACE(chan, 5); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubSw, 0x0010, 4); -+ OUT_RING (chan, upper_32_bits(offset)); -+ OUT_RING (chan, lower_32_bits(offset)); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 1); /* ACQUIRE_EQ */ -+ } else { -+ struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -+ u64 offset = vma->offset + sema->mem->start; -+ -+ ret = RING_SPACE(chan, 5); -+ if (ret) -+ return ret; -+ -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); -+ OUT_RING (chan, upper_32_bits(offset)); -+ OUT_RING (chan, lower_32_bits(offset)); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0x1001); /* ACQUIRE_EQ */ -+ } -+ -+ /* Delay semaphore destruction until its work is done */ -+ ret = nouveau_fence_new(chan, &fence, true); - if (ret) - return ret; - -- if (smart) { -- BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); -- OUT_RING(chan, NvSema); -- } -- BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); -- OUT_RING(chan, sema->mem->start); -- -- if (smart && method == NV_SW_SEMAPHORE_ACQUIRE) { -- /* -- * NV50 tries to be too smart and context-switch -- * between semaphores instead of doing a "first come, -- * first served" strategy like previous cards -- * do. -- * -- * That's bad because the ACQUIRE latency can get as -- * large as the PFIFO context time slice in the -- * typical DRI2 case where you have several -- * outstanding semaphores at the same moment. -- * -- * If we're going to ACQUIRE, force the card to -- * context switch before, just in case the matching -- * RELEASE is already scheduled to be executed in -- * another channel. -- */ -- BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); -- OUT_RING(chan, 0); -- } -+ kref_get(&sema->ref); -+ nouveau_fence_work(fence, semaphore_work, sema); -+ nouveau_fence_unref(&fence); -+ return 0; -+} -+ -+static int -+semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nouveau_fence *fence = NULL; -+ int ret; -+ -+ if (dev_priv->chipset < 0x84) { -+ ret = RING_SPACE(chan, 4); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); -+ OUT_RING (chan, sema->mem->start); -+ BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); -+ OUT_RING (chan, 1); -+ } else -+ if (dev_priv->chipset < 0xc0) { -+ struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -+ u64 offset = vma->offset + sema->mem->start; -+ -+ ret = RING_SPACE(chan, 5); -+ if (ret) -+ return ret; -+ -+ BEGIN_RING(chan, NvSubSw, 0x0010, 4); -+ OUT_RING (chan, upper_32_bits(offset)); -+ OUT_RING (chan, lower_32_bits(offset)); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 2); /* RELEASE */ -+ } else { -+ struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -+ u64 offset = vma->offset + sema->mem->start; - -- BEGIN_RING(chan, NvSubSw, method, 1); -- OUT_RING(chan, 1); -- -- if (smart && method == NV_SW_SEMAPHORE_RELEASE) { -- /* -- * Force the card to context switch, there may be -- * another channel waiting for the semaphore we just -- * released. -- */ -- BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1); -- OUT_RING(chan, 0); -+ ret = RING_SPACE(chan, 5); -+ if (ret) -+ return ret; -+ -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); -+ OUT_RING (chan, upper_32_bits(offset)); -+ OUT_RING (chan, lower_32_bits(offset)); -+ OUT_RING (chan, 1); -+ OUT_RING (chan, 0x1002); /* RELEASE */ - } - - /* Delay semaphore destruction until its work is done */ -@@ -383,7 +439,6 @@ emit_semaphore(struct nouveau_channel *chan, int method, - kref_get(&sema->ref); - nouveau_fence_work(fence, semaphore_work, sema); - nouveau_fence_unref(&fence); -- - return 0; - } - -@@ -400,7 +455,7 @@ nouveau_fence_sync(struct nouveau_fence *fence, - nouveau_fence_signalled(fence))) - goto out; - -- sema = alloc_semaphore(dev); -+ sema = semaphore_alloc(dev); - if (!sema) { - /* Early card or broken userspace, fall back to - * software sync. */ -@@ -418,17 +473,17 @@ nouveau_fence_sync(struct nouveau_fence *fence, - } - - /* Make wchan wait until it gets signalled */ -- ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); -+ ret = semaphore_acquire(wchan, sema); - if (ret) - goto out_unlock; - - /* Signal the semaphore from chan */ -- ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); -+ ret = semaphore_release(chan, sema); - - out_unlock: - mutex_unlock(&chan->mutex); - out_unref: -- kref_put(&sema->ref, free_semaphore); -+ kref_put(&sema->ref, semaphore_free); - out: - if (chan) - nouveau_channel_put_unlocked(&chan); -@@ -449,22 +504,23 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) - struct nouveau_gpuobj *obj = NULL; - int ret; - -+ if (dev_priv->card_type >= NV_C0) -+ goto out_initialised; -+ - /* Create an NV_SW object for various sync purposes */ - ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); - if (ret) - return ret; - - /* we leave subchannel empty for nvc0 */ -- if (dev_priv->card_type < NV_C0) { -- ret = RING_SPACE(chan, 2); -- if (ret) -- return ret; -- BEGIN_RING(chan, NvSubSw, 0, 1); -- OUT_RING(chan, NvSw); -- } -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ BEGIN_RING(chan, NvSubSw, 0, 1); -+ OUT_RING(chan, NvSw); - - /* Create a DMA object for the shared cross-channel sync area. */ -- if (USE_SEMA(dev)) { -+ if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { - struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -@@ -484,14 +540,20 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) - return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); - OUT_RING(chan, NvSema); -+ } else { -+ ret = RING_SPACE(chan, 2); -+ if (ret) -+ return ret; -+ BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); -+ OUT_RING (chan, chan->vram_handle); /* whole VM */ - } - - FIRE_RING(chan); - -+out_initialised: - INIT_LIST_HEAD(&chan->fence.pending); - spin_lock_init(&chan->fence.lock); - atomic_set(&chan->fence.last_sequence_irq, 0); -- - return 0; - } - -@@ -519,12 +581,13 @@ int - nouveau_fence_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int size = (dev_priv->chipset < 0x84) ? 4096 : 16384; - int ret; - - /* Create a shared VRAM heap for cross-channel sync. */ - if (USE_SEMA(dev)) { -- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, -- 0, 0, false, true, &dev_priv->fence.bo); -+ ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM, -+ 0, 0, &dev_priv->fence.bo); - if (ret) - return ret; - -diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c -index 506c508..e8b04f4 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_gem.c -+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c -@@ -61,19 +61,36 @@ nouveau_gem_object_del(struct drm_gem_object *gem) - - int - nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, -- int size, int align, uint32_t flags, uint32_t tile_mode, -- uint32_t tile_flags, bool no_vm, bool mappable, -- struct nouveau_bo **pnvbo) -+ int size, int align, uint32_t domain, uint32_t tile_mode, -+ uint32_t tile_flags, struct nouveau_bo **pnvbo) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *nvbo; -+ u32 flags = 0; - int ret; - -+ if (domain & NOUVEAU_GEM_DOMAIN_VRAM) -+ flags |= TTM_PL_FLAG_VRAM; -+ if (domain & NOUVEAU_GEM_DOMAIN_GART) -+ flags |= TTM_PL_FLAG_TT; -+ if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) -+ flags |= TTM_PL_FLAG_SYSTEM; -+ - ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, -- tile_flags, no_vm, mappable, pnvbo); -+ tile_flags, pnvbo); - if (ret) - return ret; - nvbo = *pnvbo; - -+ /* we restrict allowed domains on nv50+ to only the types -+ * that were requested at creation time. not possibly on -+ * earlier chips without busting the ABI. -+ */ -+ nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | -+ NOUVEAU_GEM_DOMAIN_GART; -+ if (dev_priv->card_type >= NV_50) -+ nvbo->valid_domains &= domain; -+ - nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); - if (!nvbo->gem) { - nouveau_bo_ref(NULL, pnvbo); -@@ -97,7 +114,7 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) - - rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; - rep->offset = nvbo->bo.offset; -- rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0; -+ rep->map_handle = nvbo->bo.addr_space_offset; - rep->tile_mode = nvbo->tile_mode; - rep->tile_flags = nvbo->tile_flags; - return 0; -@@ -111,19 +128,11 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, - struct drm_nouveau_gem_new *req = data; - struct nouveau_bo *nvbo = NULL; - struct nouveau_channel *chan = NULL; -- uint32_t flags = 0; - int ret = 0; - - if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) - dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; - -- if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) -- flags |= TTM_PL_FLAG_VRAM; -- if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) -- flags |= TTM_PL_FLAG_TT; -- if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) -- flags |= TTM_PL_FLAG_SYSTEM; -- - if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { - NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); - return -EINVAL; -@@ -135,10 +144,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, - return PTR_ERR(chan); - } - -- ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, -- req->info.tile_mode, req->info.tile_flags, false, -- (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), -- &nvbo); -+ ret = nouveau_gem_new(dev, chan, req->info.size, req->align, -+ req->info.domain, req->info.tile_mode, -+ req->info.tile_flags, &nvbo); - if (chan) - nouveau_channel_put(&chan); - if (ret) -@@ -161,7 +169,7 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, - { - struct nouveau_bo *nvbo = gem->driver_private; - struct ttm_buffer_object *bo = &nvbo->bo; -- uint32_t domains = valid_domains & -+ uint32_t domains = valid_domains & nvbo->valid_domains & - (write_domains ? write_domains : read_domains); - uint32_t pref_flags = 0, valid_flags = 0; - -@@ -592,7 +600,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, - if (push[i].bo_index >= req->nr_buffers) { - NV_ERROR(dev, "push %d buffer not in list\n", i); - ret = -EINVAL; -- goto out; -+ goto out_prevalid; - } - - bo[push[i].bo_index].read_domains |= (1 << 31); -@@ -604,7 +612,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, - if (ret) { - if (ret != -ERESTARTSYS) - NV_ERROR(dev, "validate: %d\n", ret); -- goto out; -+ goto out_prevalid; - } - - /* Apply any relocations that are required */ -@@ -697,6 +705,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, - out: - validate_fini(&op, fence); - nouveau_fence_unref(&fence); -+ -+out_prevalid: - kfree(bo); - kfree(push); - -diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h -index 4a8ad13..86c2e37 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_grctx.h -+++ b/drivers/gpu/drm/nouveau/nouveau_grctx.h -@@ -87,10 +87,10 @@ _cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name) - cp_out(ctx, CP_BRA | (mod << 18) | ip | flag | - (state ? 0 : CP_BRA_IF_CLEAR)); - } --#define cp_bra(c,f,s,n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n) -+#define cp_bra(c, f, s, n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n) - #ifdef CP_BRA_MOD --#define cp_cal(c,f,s,n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n) --#define cp_ret(c,f,s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0) -+#define cp_cal(c, f, s, n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n) -+#define cp_ret(c, f, s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0) - #endif - - static inline void -@@ -98,14 +98,14 @@ _cp_wait(struct nouveau_grctx *ctx, int flag, int state) - { - cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0)); - } --#define cp_wait(c,f,s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s) -+#define cp_wait(c, f, s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s) - - static inline void - _cp_set(struct nouveau_grctx *ctx, int flag, int state) - { - cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0)); - } --#define cp_set(c,f,s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s) -+#define cp_set(c, f, s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s) - - static inline void - cp_pos(struct nouveau_grctx *ctx, int offset) -diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c -index 053edf9..ba896e5 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_hw.c -+++ b/drivers/gpu/drm/nouveau/nouveau_hw.c -@@ -900,6 +900,7 @@ nv_save_state_ext(struct drm_device *dev, int head, - } - /* NV11 and NV20 don't have this, they stop at 0x52. */ - if (nv_gf4_disp_arch(dev)) { -+ rd_cio_state(dev, head, regp, NV_CIO_CRE_42); - rd_cio_state(dev, head, regp, NV_CIO_CRE_53); - rd_cio_state(dev, head, regp, NV_CIO_CRE_54); - -@@ -1003,6 +1004,7 @@ nv_load_state_ext(struct drm_device *dev, int head, - nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); - } - -+ wr_cio_state(dev, head, regp, NV_CIO_CRE_42); - wr_cio_state(dev, head, regp, NV_CIO_CRE_53); - wr_cio_state(dev, head, regp, NV_CIO_CRE_54); - -diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index b0fb9bd..4942294 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_mem.c -+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c -@@ -152,9 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -- nouveau_bo_unpin(dev_priv->vga_ram); -- nouveau_bo_ref(NULL, &dev_priv->vga_ram); -- - ttm_bo_device_release(&dev_priv->ttm.bdev); - - nouveau_ttm_global_release(dev_priv); -@@ -393,11 +390,17 @@ nouveau_mem_vram_init(struct drm_device *dev) - struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - int ret, dma_bits; - -- if (dev_priv->card_type >= NV_50 && -- pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) -- dma_bits = 40; -- else -- dma_bits = 32; -+ dma_bits = 32; -+ if (dev_priv->card_type >= NV_50) { -+ if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40))) -+ dma_bits = 40; -+ } else -+ if (0 && drm_device_is_pcie(dev) && -+ dev_priv->chipset > 0x40 && -+ dev_priv->chipset != 0x45) { -+ if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39))) -+ dma_bits = 39; -+ } - - ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); - if (ret) -@@ -419,14 +422,32 @@ nouveau_mem_vram_init(struct drm_device *dev) - } - - /* reserve space at end of VRAM for PRAMIN */ -- if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 || -- dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) -- dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); -- else -- if (dev_priv->card_type >= NV_40) -- dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); -- else -- dev_priv->ramin_rsvd_vram = (512 * 1024); -+ if (dev_priv->card_type >= NV_50) { -+ dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; -+ } else -+ if (dev_priv->card_type >= NV_40) { -+ u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); -+ u32 rsvd; -+ -+ /* estimate grctx size, the magics come from nv40_grctx.c */ -+ if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; -+ else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; -+ else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; -+ else rsvd = 0x4a40 * vs; -+ rsvd += 16 * 1024; -+ rsvd *= dev_priv->engine.fifo.channels; -+ -+ /* pciegart table */ -+ if (drm_device_is_pcie(dev)) -+ rsvd += 512 * 1024; -+ -+ /* object storage */ -+ rsvd += 512 * 1024; -+ -+ dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); -+ } else { -+ dev_priv->ramin_rsvd_vram = 512 * 1024; -+ } - - ret = dev_priv->engine.vram.init(dev); - if (ret) -@@ -455,13 +476,17 @@ nouveau_mem_vram_init(struct drm_device *dev) - return ret; - } - -- ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, -- 0, 0, true, true, &dev_priv->vga_ram); -- if (ret == 0) -- ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM); -- if (ret) { -- NV_WARN(dev, "failed to reserve VGA memory\n"); -- nouveau_bo_ref(NULL, &dev_priv->vga_ram); -+ if (dev_priv->card_type < NV_50) { -+ ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, -+ 0, 0, &dev_priv->vga_ram); -+ if (ret == 0) -+ ret = nouveau_bo_pin(dev_priv->vga_ram, -+ TTM_PL_FLAG_VRAM); -+ -+ if (ret) { -+ NV_WARN(dev, "failed to reserve VGA memory\n"); -+ nouveau_bo_ref(NULL, &dev_priv->vga_ram); -+ } - } - - dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1), -@@ -525,6 +550,7 @@ nouveau_mem_timing_init(struct drm_device *dev) - u8 tRC; /* Byte 9 */ - u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; - u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; -+ u8 magic_number = 0; /* Yeah... sorry*/ - u8 *mem = NULL, *entry; - int i, recordlen, entries; - -@@ -569,6 +595,12 @@ nouveau_mem_timing_init(struct drm_device *dev) - if (!memtimings->timing) - return; - -+ /* Get "some number" from the timing reg for NV_40 and NV_50 -+ * Used in calculations later */ -+ if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) { -+ magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; -+ } -+ - entry = mem + mem[1]; - for (i = 0; i < entries; i++, entry += recordlen) { - struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; -@@ -608,36 +640,67 @@ nouveau_mem_timing_init(struct drm_device *dev) - - /* XXX: I don't trust the -1's and +1's... they must come - * from somewhere! */ -- timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 | -- tUNK_18 << 16 | -- (tUNK_1 + tUNK_19 + 1) << 8 | -- (tUNK_2 - 1)); -+ timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 | -+ max(tUNK_18, (u8) 1) << 16 | -+ (tUNK_1 + tUNK_19 + 1 + magic_number) << 8; -+ if (dev_priv->chipset == 0xa8) { -+ timing->reg_100224 |= (tUNK_2 - 1); -+ } else { -+ timing->reg_100224 |= (tUNK_2 + 2 - magic_number); -+ } - - timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); -- if(recordlen > 19) { -- timing->reg_100228 += (tUNK_19 - 1) << 24; -- }/* I cannot back-up this else-statement right now -- else { -- timing->reg_100228 += tUNK_12 << 24; -- }*/ -- -- /* XXX: reg_10022c */ -- timing->reg_10022c = tUNK_2 - 1; -- -- timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | -- tUNK_13 << 8 | tUNK_13); -- -- /* XXX: +6? */ -- timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC); -- timing->reg_100234 += max(tUNK_10,tUNK_11) << 16; -- -- /* XXX; reg_100238, reg_10023c -- * reg: 0x00?????? -- * reg_10023c: -- * 0 for pre-NV50 cards -- * 0x????0202 for NV50+ cards (empirical evidence) */ -- if(dev_priv->card_type >= NV_50) { -+ if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) -+ timing->reg_100228 |= (tUNK_19 - 1) << 24; -+ else -+ timing->reg_100228 |= magic_number << 24; -+ -+ if (dev_priv->card_type == NV_40) { -+ /* NV40: don't know what the rest of the regs are.. -+ * And don't need to know either */ -+ timing->reg_100228 |= 0x20200000; -+ } else if (dev_priv->card_type >= NV_50) { -+ if (dev_priv->chipset < 0x98 || -+ (dev_priv->chipset == 0x98 && -+ dev_priv->stepping <= 0xa1)) { -+ timing->reg_10022c = (0x14 + tUNK_2) << 24 | -+ 0x16 << 16 | -+ (tUNK_2 - 1) << 8 | -+ (tUNK_2 - 1); -+ } else { -+ /* XXX: reg_10022c for recentish cards */ -+ timing->reg_10022c = tUNK_2 - 1; -+ } -+ -+ timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | -+ tUNK_13 << 8 | tUNK_13); -+ -+ timing->reg_100234 = (tRAS << 24 | tRC); -+ timing->reg_100234 += max(tUNK_10, tUNK_11) << 16; -+ -+ if (dev_priv->chipset < 0x98 || -+ (dev_priv->chipset == 0x98 && -+ dev_priv->stepping <= 0xa1)) { -+ timing->reg_100234 |= (tUNK_2 + 2) << 8; -+ } else { -+ /* XXX: +6? */ -+ timing->reg_100234 |= (tUNK_19 + 6) << 8; -+ } -+ -+ /* XXX; reg_100238 -+ * reg_100238: 0x00?????? */ - timing->reg_10023c = 0x202; -+ if (dev_priv->chipset < 0x98 || -+ (dev_priv->chipset == 0x98 && -+ dev_priv->stepping <= 0xa1)) { -+ timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16; -+ } else { -+ /* XXX: reg_10023c -+ * currently unknown -+ * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ -+ } -+ -+ /* XXX: reg_100240? */ - } - - NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, -@@ -646,9 +709,10 @@ nouveau_mem_timing_init(struct drm_device *dev) - NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", - timing->reg_100230, timing->reg_100234, - timing->reg_100238, timing->reg_10023c); -+ NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240); - } - -- memtimings->nr_timing = entries; -+ memtimings->nr_timing = entries; - memtimings->supported = true; - } - -@@ -666,13 +730,14 @@ nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct nouveau_mm *mm; -- u32 b_size; -+ u64 size, block, rsvd; - int ret; - -- p_size = (p_size << PAGE_SHIFT) >> 12; -- b_size = dev_priv->vram_rblock_size >> 12; -+ rsvd = (256 * 1024); /* vga memory */ -+ size = (p_size << PAGE_SHIFT) - rsvd; -+ block = dev_priv->vram_rblock_size; - -- ret = nouveau_mm_init(&mm, 0, p_size, b_size); -+ ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12); - if (ret) - return ret; - -@@ -700,9 +765,15 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man, - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ struct nouveau_mem *node = mem->mm_node; - struct drm_device *dev = dev_priv->dev; - -- vram->put(dev, (struct nouveau_vram **)&mem->mm_node); -+ if (node->tmp_vma.node) { -+ nouveau_vm_unmap(&node->tmp_vma); -+ nouveau_vm_put(&node->tmp_vma); -+ } -+ -+ vram->put(dev, (struct nouveau_mem **)&mem->mm_node); - } - - static int -@@ -715,7 +786,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; - struct drm_device *dev = dev_priv->dev; - struct nouveau_bo *nvbo = nouveau_bo(bo); -- struct nouveau_vram *node; -+ struct nouveau_mem *node; - u32 size_nc = 0; - int ret; - -@@ -724,7 +795,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, - - ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, - mem->page_alignment << PAGE_SHIFT, size_nc, -- (nvbo->tile_flags >> 8) & 0xff, &node); -+ (nvbo->tile_flags >> 8) & 0x3ff, &node); - if (ret) { - mem->mm_node = NULL; - return (ret == -ENOSPC) ? 0 : ret; -@@ -771,3 +842,84 @@ const struct ttm_mem_type_manager_func nouveau_vram_manager = { - nouveau_vram_manager_del, - nouveau_vram_manager_debug - }; -+ -+static int -+nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) -+{ -+ return 0; -+} -+ -+static int -+nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) -+{ -+ return 0; -+} -+ -+static void -+nouveau_gart_manager_del(struct ttm_mem_type_manager *man, -+ struct ttm_mem_reg *mem) -+{ -+ struct nouveau_mem *node = mem->mm_node; -+ -+ if (node->tmp_vma.node) { -+ nouveau_vm_unmap(&node->tmp_vma); -+ nouveau_vm_put(&node->tmp_vma); -+ } -+ mem->mm_node = NULL; -+} -+ -+static int -+nouveau_gart_manager_new(struct ttm_mem_type_manager *man, -+ struct ttm_buffer_object *bo, -+ struct ttm_placement *placement, -+ struct ttm_mem_reg *mem) -+{ -+ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -+ struct nouveau_bo *nvbo = nouveau_bo(bo); -+ struct nouveau_vma *vma = &nvbo->vma; -+ struct nouveau_vm *vm = vma->vm; -+ struct nouveau_mem *node; -+ int ret; -+ -+ if (unlikely((mem->num_pages << PAGE_SHIFT) >= -+ dev_priv->gart_info.aper_size)) -+ return -ENOMEM; -+ -+ node = kzalloc(sizeof(*node), GFP_KERNEL); -+ if (!node) -+ return -ENOMEM; -+ -+ /* This node must be for evicting large-paged VRAM -+ * to system memory. Due to a nv50 limitation of -+ * not being able to mix large/small pages within -+ * the same PDE, we need to create a temporary -+ * small-paged VMA for the eviction. -+ */ -+ if (vma->node->type != vm->spg_shift) { -+ ret = nouveau_vm_get(vm, (u64)vma->node->length << 12, -+ vm->spg_shift, NV_MEM_ACCESS_RW, -+ &node->tmp_vma); -+ if (ret) { -+ kfree(node); -+ return ret; -+ } -+ } -+ -+ node->page_shift = nvbo->vma.node->type; -+ mem->mm_node = node; -+ mem->start = 0; -+ return 0; -+} -+ -+void -+nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) -+{ -+} -+ -+const struct ttm_mem_type_manager_func nouveau_gart_manager = { -+ nouveau_gart_manager_init, -+ nouveau_gart_manager_fini, -+ nouveau_gart_manager_new, -+ nouveau_gart_manager_del, -+ nouveau_gart_manager_debug -+}; -diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h -index 798eaf3..1f7483a 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_mm.h -+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h -@@ -53,13 +53,13 @@ void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); - - int nv50_vram_init(struct drm_device *); - int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, -- u32 memtype, struct nouveau_vram **); --void nv50_vram_del(struct drm_device *, struct nouveau_vram **); -+ u32 memtype, struct nouveau_mem **); -+void nv50_vram_del(struct drm_device *, struct nouveau_mem **); - bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); - - int nvc0_vram_init(struct drm_device *); - int nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin, -- u32 memtype, struct nouveau_vram **); -+ u32 memtype, struct nouveau_mem **); - bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags); - - #endif -diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c -index 5ea1676..5b39718 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_notifier.c -+++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c -@@ -35,20 +35,22 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; - struct nouveau_bo *ntfy = NULL; -- uint32_t flags; -+ uint32_t flags, ttmpl; - int ret; - -- if (nouveau_vram_notify) -- flags = TTM_PL_FLAG_VRAM; -- else -- flags = TTM_PL_FLAG_TT; -+ if (nouveau_vram_notify) { -+ flags = NOUVEAU_GEM_DOMAIN_VRAM; -+ ttmpl = TTM_PL_FLAG_VRAM; -+ } else { -+ flags = NOUVEAU_GEM_DOMAIN_GART; -+ ttmpl = TTM_PL_FLAG_TT; -+ } - -- ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, -- 0, 0x0000, false, true, &ntfy); -+ ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy); - if (ret) - return ret; - -- ret = nouveau_bo_pin(ntfy, flags); -+ ret = nouveau_bo_pin(ntfy, ttmpl); - if (ret) - goto out_err; - -@@ -100,6 +102,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, - uint32_t *b_offset) - { - struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *nobj = NULL; - struct drm_mm_node *mem; - uint32_t offset; -@@ -114,11 +117,16 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, - return -ENOMEM; - } - -- if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) -- target = NV_MEM_TARGET_VRAM; -- else -- target = NV_MEM_TARGET_GART; -- offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; -+ if (dev_priv->card_type < NV_50) { -+ if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) -+ target = NV_MEM_TARGET_VRAM; -+ else -+ target = NV_MEM_TARGET_GART; -+ offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; -+ } else { -+ target = NV_MEM_TARGET_VM; -+ offset = chan->notifier_bo->vma.offset; -+ } - offset += mem->start; - - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, -diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c -index 30b6544..59b446e 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_object.c -+++ b/drivers/gpu/drm/nouveau/nouveau_object.c -@@ -36,6 +36,7 @@ - #include "nouveau_drm.h" - #include "nouveau_ramht.h" - #include "nouveau_vm.h" -+#include "nv50_display.h" - - struct nouveau_gpuobj_method { - struct list_head head; -@@ -490,16 +491,22 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, - } - - if (target == NV_MEM_TARGET_GART) { -- if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { -- target = NV_MEM_TARGET_PCI_NOSNOOP; -- base += dev_priv->gart_info.aper_base; -- } else -- if (base != 0) { -- base = nouveau_sgdma_get_physical(dev, base); -+ struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; -+ -+ if (dev_priv->gart_info.type == NOUVEAU_GART_PDMA) { -+ if (base == 0) { -+ nouveau_gpuobj_ref(gart, pobj); -+ return 0; -+ } -+ -+ base = nouveau_sgdma_get_physical(dev, base); - target = NV_MEM_TARGET_PCI; - } else { -- nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj); -- return 0; -+ base += dev_priv->gart_info.aper_base; -+ if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) -+ target = NV_MEM_TARGET_PCI_NOSNOOP; -+ else -+ target = NV_MEM_TARGET_PCI; - } - } - -@@ -776,7 +783,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *vram = NULL, *tt = NULL; -- int ret; -+ int ret, i; - - NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); - -@@ -841,6 +848,25 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, - nouveau_gpuobj_ref(NULL, &ramht); - if (ret) - return ret; -+ -+ /* dma objects for display sync channel semaphore blocks */ -+ for (i = 0; i < 2; i++) { -+ struct nouveau_gpuobj *sem = NULL; -+ struct nv50_display_crtc *dispc = -+ &nv50_display(dev)->crtc[i]; -+ u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; -+ -+ ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff, -+ NV_MEM_ACCESS_RW, -+ NV_MEM_TARGET_VRAM, &sem); -+ if (ret) -+ return ret; -+ -+ ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, sem); -+ nouveau_gpuobj_ref(NULL, &sem); -+ if (ret) -+ return ret; -+ } - } - - /* VRAM ctxdma */ -@@ -1013,19 +1039,20 @@ nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) - { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_device *dev = gpuobj->dev; -+ unsigned long flags; - - if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { - u64 ptr = gpuobj->vinst + offset; - u32 base = ptr >> 16; - u32 val; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - if (dev_priv->ramin_base != base) { - dev_priv->ramin_base = base; - nv_wr32(dev, 0x001700, dev_priv->ramin_base); - } - val = nv_rd32(dev, 0x700000 + (ptr & 0xffff)); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - return val; - } - -@@ -1037,18 +1064,19 @@ nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) - { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_device *dev = gpuobj->dev; -+ unsigned long flags; - - if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) { - u64 ptr = gpuobj->vinst + offset; - u32 base = ptr >> 16; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - if (dev_priv->ramin_base != base) { - dev_priv->ramin_base = base; - nv_wr32(dev, 0x001700, dev_priv->ramin_base); - } - nv_wr32(dev, 0x700000 + (ptr & 0xffff), val); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - return; - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c -index ac62a1b..3045566 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_perf.c -+++ b/drivers/gpu/drm/nouveau/nouveau_perf.c -@@ -134,7 +134,7 @@ nouveau_perf_init(struct drm_device *dev) - case 0x13: - case 0x15: - perflvl->fanspeed = entry[55]; -- perflvl->voltage = entry[56]; -+ perflvl->voltage = (recordlen > 56) ? entry[56] : 0; - perflvl->core = ROM32(entry[1]) * 10; - perflvl->memory = ROM32(entry[5]) * 20; - break; -@@ -174,9 +174,21 @@ nouveau_perf_init(struct drm_device *dev) - #define subent(n) entry[perf[2] + ((n) * perf[3])] - perflvl->fanspeed = 0; /*XXX*/ - perflvl->voltage = entry[2]; -- perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000; -- perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000; -- perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000; -+ if (dev_priv->card_type == NV_50) { -+ perflvl->core = ROM16(subent(0)) & 0xfff; -+ perflvl->shader = ROM16(subent(1)) & 0xfff; -+ perflvl->memory = ROM16(subent(2)) & 0xfff; -+ } else { -+ perflvl->shader = ROM16(subent(3)) & 0xfff; -+ perflvl->core = perflvl->shader / 2; -+ perflvl->unk0a = ROM16(subent(4)) & 0xfff; -+ perflvl->memory = ROM16(subent(5)) & 0xfff; -+ } -+ -+ perflvl->core *= 1000; -+ perflvl->shader *= 1000; -+ perflvl->memory *= 1000; -+ perflvl->unk0a *= 1000; - break; - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c -index 4399e2f..0b1caeb 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_pm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c -@@ -490,6 +490,7 @@ nouveau_pm_init(struct drm_device *dev) - /* determine current ("boot") performance level */ - ret = nouveau_pm_perflvl_get(dev, &pm->boot); - if (ret == 0) { -+ strncpy(pm->boot.name, "boot", 4); - pm->cur = &pm->boot; - - nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); -diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c -index bef3e69..a24a81f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_ramht.c -+++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c -@@ -114,7 +114,9 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, - (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); - } else { - if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { -- ctx = (gpuobj->cinst << 10) | chan->id; -+ ctx = (gpuobj->cinst << 10) | -+ (chan->id << 28) | -+ chan->id; /* HASH_TAG */ - } else { - ctx = (gpuobj->cinst >> 4) | - ((gpuobj->engine << -diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h -index 04e8fb7..f18cdfc 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_reg.h -+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h -@@ -639,9 +639,9 @@ - # define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240 - # define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258 - --#define NV50_AUXCH_DATA_OUT(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4c0) -+#define NV50_AUXCH_DATA_OUT(i, n) ((n) * 4 + (i) * 0x50 + 0x0000e4c0) - #define NV50_AUXCH_DATA_OUT__SIZE 4 --#define NV50_AUXCH_DATA_IN(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4d0) -+#define NV50_AUXCH_DATA_IN(i, n) ((n) * 4 + (i) * 0x50 + 0x0000e4d0) - #define NV50_AUXCH_DATA_IN__SIZE 4 - #define NV50_AUXCH_ADDR(i) ((i) * 0x50 + 0x0000e4e0) - #define NV50_AUXCH_CTRL(i) ((i) * 0x50 + 0x0000e4e4) -@@ -829,7 +829,7 @@ - #define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084 - #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 - #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff --#define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) -+#define NV50_SOR_DP_CTRL(i, l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) - #define NV50_SOR_DP_CTRL_ENABLED 0x00000001 - #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 - #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 -@@ -841,10 +841,10 @@ - #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_DISABLED 0x00000000 - #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_1 0x01000000 - #define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000 --#define NV50_SOR_DP_UNK118(i,l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) --#define NV50_SOR_DP_UNK120(i,l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) --#define NV50_SOR_DP_UNK128(i,l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) --#define NV50_SOR_DP_UNK130(i,l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) -+#define NV50_SOR_DP_UNK118(i, l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) -+#define NV50_SOR_DP_UNK120(i, l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) -+#define NV50_SOR_DP_UNK128(i, l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) -+#define NV50_SOR_DP_UNK130(i, l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) - - #define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) - #define NV50_PDISPLAY_USER_PUT(i) ((i) * 0x1000 + 0x00640000) -diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 9a250eb..2bf9686 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c -+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -@@ -74,8 +74,24 @@ nouveau_sgdma_clear(struct ttm_backend *be) - } - } - -+static void -+nouveau_sgdma_destroy(struct ttm_backend *be) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ -+ if (be) { -+ NV_DEBUG(nvbe->dev, "\n"); -+ -+ if (nvbe) { -+ if (nvbe->pages) -+ be->func->clear(be); -+ kfree(nvbe); -+ } -+ } -+} -+ - static int --nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) -+nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; - struct drm_device *dev = nvbe->dev; -@@ -102,7 +118,7 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - } - - static int --nouveau_sgdma_unbind(struct ttm_backend *be) -+nv04_sgdma_unbind(struct ttm_backend *be) - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; - struct drm_device *dev = nvbe->dev; -@@ -125,59 +141,245 @@ nouveau_sgdma_unbind(struct ttm_backend *be) - return 0; - } - -+static struct ttm_backend_func nv04_sgdma_backend = { -+ .populate = nouveau_sgdma_populate, -+ .clear = nouveau_sgdma_clear, -+ .bind = nv04_sgdma_bind, -+ .unbind = nv04_sgdma_unbind, -+ .destroy = nouveau_sgdma_destroy -+}; -+ - static void --nouveau_sgdma_destroy(struct ttm_backend *be) -+nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe) -+{ -+ struct drm_device *dev = nvbe->dev; -+ -+ nv_wr32(dev, 0x100810, 0x00000022); -+ if (!nv_wait(dev, 0x100810, 0x00000100, 0x00000100)) -+ NV_ERROR(dev, "vm flush timeout: 0x%08x\n", -+ nv_rd32(dev, 0x100810)); -+ nv_wr32(dev, 0x100810, 0x00000000); -+} -+ -+static int -+nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; -+ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; -+ dma_addr_t *list = nvbe->pages; -+ u32 pte = mem->start << 2; -+ u32 cnt = nvbe->nr_pages; - -- if (be) { -- NV_DEBUG(nvbe->dev, "\n"); -+ nvbe->offset = mem->start << PAGE_SHIFT; - -- if (nvbe) { -- if (nvbe->pages) -- be->func->clear(be); -- kfree(nvbe); -+ while (cnt--) { -+ nv_wo32(pgt, pte, (*list++ >> 7) | 1); -+ pte += 4; -+ } -+ -+ nv41_sgdma_flush(nvbe); -+ nvbe->bound = true; -+ return 0; -+} -+ -+static int -+nv41_sgdma_unbind(struct ttm_backend *be) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; -+ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; -+ u32 pte = (nvbe->offset >> 12) << 2; -+ u32 cnt = nvbe->nr_pages; -+ -+ while (cnt--) { -+ nv_wo32(pgt, pte, 0x00000000); -+ pte += 4; -+ } -+ -+ nv41_sgdma_flush(nvbe); -+ nvbe->bound = false; -+ return 0; -+} -+ -+static struct ttm_backend_func nv41_sgdma_backend = { -+ .populate = nouveau_sgdma_populate, -+ .clear = nouveau_sgdma_clear, -+ .bind = nv41_sgdma_bind, -+ .unbind = nv41_sgdma_unbind, -+ .destroy = nouveau_sgdma_destroy -+}; -+ -+static void -+nv44_sgdma_flush(struct nouveau_sgdma_be *nvbe) -+{ -+ struct drm_device *dev = nvbe->dev; -+ -+ nv_wr32(dev, 0x100814, (nvbe->nr_pages - 1) << 12); -+ nv_wr32(dev, 0x100808, nvbe->offset | 0x20); -+ if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001)) -+ NV_ERROR(dev, "gart flush timeout: 0x%08x\n", -+ nv_rd32(dev, 0x100808)); -+ nv_wr32(dev, 0x100808, 0x00000000); -+} -+ -+static void -+nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt) -+{ -+ struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; -+ dma_addr_t dummy = dev_priv->gart_info.dummy.addr; -+ u32 pte, tmp[4]; -+ -+ pte = base >> 2; -+ base &= ~0x0000000f; -+ -+ tmp[0] = nv_ro32(pgt, base + 0x0); -+ tmp[1] = nv_ro32(pgt, base + 0x4); -+ tmp[2] = nv_ro32(pgt, base + 0x8); -+ tmp[3] = nv_ro32(pgt, base + 0xc); -+ while (cnt--) { -+ u32 addr = list ? (*list++ >> 12) : (dummy >> 12); -+ switch (pte++ & 0x3) { -+ case 0: -+ tmp[0] &= ~0x07ffffff; -+ tmp[0] |= addr; -+ break; -+ case 1: -+ tmp[0] &= ~0xf8000000; -+ tmp[0] |= addr << 27; -+ tmp[1] &= ~0x003fffff; -+ tmp[1] |= addr >> 5; -+ break; -+ case 2: -+ tmp[1] &= ~0xffc00000; -+ tmp[1] |= addr << 22; -+ tmp[2] &= ~0x0001ffff; -+ tmp[2] |= addr >> 10; -+ break; -+ case 3: -+ tmp[2] &= ~0xfffe0000; -+ tmp[2] |= addr << 17; -+ tmp[3] &= ~0x00000fff; -+ tmp[3] |= addr >> 15; -+ break; - } - } -+ -+ tmp[3] |= 0x40000000; -+ -+ nv_wo32(pgt, base + 0x0, tmp[0]); -+ nv_wo32(pgt, base + 0x4, tmp[1]); -+ nv_wo32(pgt, base + 0x8, tmp[2]); -+ nv_wo32(pgt, base + 0xc, tmp[3]); - } - - static int --nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) -+nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; - struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; -+ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; -+ dma_addr_t *list = nvbe->pages; -+ u32 pte = mem->start << 2, tmp[4]; -+ u32 cnt = nvbe->nr_pages; -+ int i; - - nvbe->offset = mem->start << PAGE_SHIFT; - -- nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset, -- nvbe->nr_pages << PAGE_SHIFT, nvbe->pages); -+ if (pte & 0x0000000c) { -+ u32 max = 4 - ((pte >> 2) & 0x3); -+ u32 part = (cnt > max) ? max : cnt; -+ nv44_sgdma_fill(pgt, list, pte, part); -+ pte += (part << 2); -+ list += part; -+ cnt -= part; -+ } -+ -+ while (cnt >= 4) { -+ for (i = 0; i < 4; i++) -+ tmp[i] = *list++ >> 12; -+ nv_wo32(pgt, pte + 0x0, tmp[0] >> 0 | tmp[1] << 27); -+ nv_wo32(pgt, pte + 0x4, tmp[1] >> 5 | tmp[2] << 22); -+ nv_wo32(pgt, pte + 0x8, tmp[2] >> 10 | tmp[3] << 17); -+ nv_wo32(pgt, pte + 0xc, tmp[3] >> 15 | 0x40000000); -+ pte += 0x10; -+ cnt -= 4; -+ } -+ -+ if (cnt) -+ nv44_sgdma_fill(pgt, list, pte, cnt); -+ -+ nv44_sgdma_flush(nvbe); - nvbe->bound = true; - return 0; - } - - static int --nv50_sgdma_unbind(struct ttm_backend *be) -+nv44_sgdma_unbind(struct ttm_backend *be) - { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; - struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; -+ struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma; -+ u32 pte = (nvbe->offset >> 12) << 2; -+ u32 cnt = nvbe->nr_pages; -+ -+ if (pte & 0x0000000c) { -+ u32 max = 4 - ((pte >> 2) & 0x3); -+ u32 part = (cnt > max) ? max : cnt; -+ nv44_sgdma_fill(pgt, NULL, pte, part); -+ pte += (part << 2); -+ cnt -= part; -+ } - -- if (!nvbe->bound) -- return 0; -+ while (cnt >= 4) { -+ nv_wo32(pgt, pte + 0x0, 0x00000000); -+ nv_wo32(pgt, pte + 0x4, 0x00000000); -+ nv_wo32(pgt, pte + 0x8, 0x00000000); -+ nv_wo32(pgt, pte + 0xc, 0x00000000); -+ pte += 0x10; -+ cnt -= 4; -+ } - -- nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset, -- nvbe->nr_pages << PAGE_SHIFT); -+ if (cnt) -+ nv44_sgdma_fill(pgt, NULL, pte, cnt); -+ -+ nv44_sgdma_flush(nvbe); - nvbe->bound = false; - return 0; - } - --static struct ttm_backend_func nouveau_sgdma_backend = { -+static struct ttm_backend_func nv44_sgdma_backend = { - .populate = nouveau_sgdma_populate, - .clear = nouveau_sgdma_clear, -- .bind = nouveau_sgdma_bind, -- .unbind = nouveau_sgdma_unbind, -+ .bind = nv44_sgdma_bind, -+ .unbind = nv44_sgdma_unbind, - .destroy = nouveau_sgdma_destroy - }; - -+static int -+nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct nouveau_mem *node = mem->mm_node; -+ /* noop: bound in move_notify() */ -+ node->pages = nvbe->pages; -+ nvbe->pages = (dma_addr_t *)node; -+ nvbe->bound = true; -+ return 0; -+} -+ -+static int -+nv50_sgdma_unbind(struct ttm_backend *be) -+{ -+ struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; -+ struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages; -+ /* noop: unbound in move_notify() */ -+ nvbe->pages = node->pages; -+ node->pages = NULL; -+ nvbe->bound = false; -+ return 0; -+} -+ - static struct ttm_backend_func nv50_sgdma_backend = { - .populate = nouveau_sgdma_populate, - .clear = nouveau_sgdma_clear, -@@ -198,10 +400,7 @@ nouveau_sgdma_init_ttm(struct drm_device *dev) - - nvbe->dev = dev; - -- if (dev_priv->card_type < NV_50) -- nvbe->backend.func = &nouveau_sgdma_backend; -- else -- nvbe->backend.func = &nv50_sgdma_backend; -+ nvbe->backend.func = dev_priv->gart_info.func; - return &nvbe->backend; - } - -@@ -210,21 +409,64 @@ nouveau_sgdma_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = NULL; -- uint32_t aper_size, obj_size; -- int i, ret; -+ u32 aper_size, align; -+ int ret; - -- if (dev_priv->card_type < NV_50) { -- if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) -- aper_size = 64 * 1024 * 1024; -- else -- aper_size = 512 * 1024 * 1024; -+ if (dev_priv->card_type >= NV_40 && drm_device_is_pcie(dev)) -+ aper_size = 512 * 1024 * 1024; -+ else -+ aper_size = 64 * 1024 * 1024; -+ -+ /* Dear NVIDIA, NV44+ would like proper present bits in PTEs for -+ * christmas. The cards before it have them, the cards after -+ * it have them, why is NV44 so unloved? -+ */ -+ dev_priv->gart_info.dummy.page = alloc_page(GFP_DMA32 | GFP_KERNEL); -+ if (!dev_priv->gart_info.dummy.page) -+ return -ENOMEM; - -- obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; -- obj_size += 8; /* ctxdma header */ -+ dev_priv->gart_info.dummy.addr = -+ pci_map_page(dev->pdev, dev_priv->gart_info.dummy.page, -+ 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ if (pci_dma_mapping_error(dev->pdev, dev_priv->gart_info.dummy.addr)) { -+ NV_ERROR(dev, "error mapping dummy page\n"); -+ __free_page(dev_priv->gart_info.dummy.page); -+ dev_priv->gart_info.dummy.page = NULL; -+ return -ENOMEM; -+ } - -- ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, -- NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &gpuobj); -+ if (dev_priv->card_type >= NV_50) { -+ dev_priv->gart_info.aper_base = 0; -+ dev_priv->gart_info.aper_size = aper_size; -+ dev_priv->gart_info.type = NOUVEAU_GART_HW; -+ dev_priv->gart_info.func = &nv50_sgdma_backend; -+ } else -+ if (0 && drm_device_is_pcie(dev) && -+ dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) { -+ if (nv44_graph_class(dev)) { -+ dev_priv->gart_info.func = &nv44_sgdma_backend; -+ align = 512 * 1024; -+ } else { -+ dev_priv->gart_info.func = &nv41_sgdma_backend; -+ align = 16; -+ } -+ -+ ret = nouveau_gpuobj_new(dev, NULL, aper_size / 1024, align, -+ NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &gpuobj); -+ if (ret) { -+ NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); -+ return ret; -+ } -+ -+ dev_priv->gart_info.sg_ctxdma = gpuobj; -+ dev_priv->gart_info.aper_base = 0; -+ dev_priv->gart_info.aper_size = aper_size; -+ dev_priv->gart_info.type = NOUVEAU_GART_HW; -+ } else { -+ ret = nouveau_gpuobj_new(dev, NULL, (aper_size / 1024) + 8, 16, -+ NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &gpuobj); - if (ret) { - NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); - return ret; -@@ -236,25 +478,14 @@ nouveau_sgdma_init(struct drm_device *dev) - (0 << 14) /* RW */ | - (2 << 16) /* PCI */); - nv_wo32(gpuobj, 4, aper_size - 1); -- for (i = 2; i < 2 + (aper_size >> 12); i++) -- nv_wo32(gpuobj, i * 4, 0x00000000); - - dev_priv->gart_info.sg_ctxdma = gpuobj; - dev_priv->gart_info.aper_base = 0; - dev_priv->gart_info.aper_size = aper_size; -- } else -- if (dev_priv->chan_vm) { -- ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024, -- 12, NV_MEM_ACCESS_RW, -- &dev_priv->gart_info.vma); -- if (ret) -- return ret; -- -- dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset; -- dev_priv->gart_info.aper_size = 512 * 1024 * 1024; -+ dev_priv->gart_info.type = NOUVEAU_GART_PDMA; -+ dev_priv->gart_info.func = &nv04_sgdma_backend; - } - -- dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; - return 0; - } - -@@ -264,7 +495,13 @@ nouveau_sgdma_takedown(struct drm_device *dev) - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); -- nouveau_vm_put(&dev_priv->gart_info.vma); -+ -+ if (dev_priv->gart_info.dummy.page) { -+ pci_unmap_page(dev->pdev, dev_priv->gart_info.dummy.addr, -+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ __free_page(dev_priv->gart_info.dummy.page); -+ dev_priv->gart_info.dummy.page = NULL; -+ } - } - - uint32_t -diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c -index a54fc43..adf6dac 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_state.c -+++ b/drivers/gpu/drm/nouveau/nouveau_state.c -@@ -376,15 +376,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->graph.destroy_context = nv50_graph_destroy_context; - engine->graph.load_context = nv50_graph_load_context; - engine->graph.unload_context = nv50_graph_unload_context; -- if (dev_priv->chipset != 0x86) -+ if (dev_priv->chipset == 0x50 || -+ dev_priv->chipset == 0xac) - engine->graph.tlb_flush = nv50_graph_tlb_flush; -- else { -- /* from what i can see nvidia do this on every -- * pre-NVA3 board except NVAC, but, we've only -- * ever seen problems on NV86 -- */ -- engine->graph.tlb_flush = nv86_graph_tlb_flush; -- } -+ else -+ engine->graph.tlb_flush = nv84_graph_tlb_flush; - engine->fifo.channels = 128; - engine->fifo.init = nv50_fifo_init; - engine->fifo.takedown = nv50_fifo_takedown; -@@ -513,6 +509,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; -+ engine->pm.temp_get = nv84_temp_get; - break; - default: - NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); -@@ -544,7 +541,6 @@ static int - nouveau_card_init_channel(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *gpuobj = NULL; - int ret; - - ret = nouveau_channel_alloc(dev, &dev_priv->channel, -@@ -552,41 +548,8 @@ nouveau_card_init_channel(struct drm_device *dev) - if (ret) - return ret; - -- /* no dma objects on fermi... */ -- if (dev_priv->card_type >= NV_C0) -- goto out_done; -- -- ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, -- 0, dev_priv->vram_size, -- NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM, -- &gpuobj); -- if (ret) -- goto out_err; -- -- ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj); -- nouveau_gpuobj_ref(NULL, &gpuobj); -- if (ret) -- goto out_err; -- -- ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, -- 0, dev_priv->gart_info.aper_size, -- NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART, -- &gpuobj); -- if (ret) -- goto out_err; -- -- ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj); -- nouveau_gpuobj_ref(NULL, &gpuobj); -- if (ret) -- goto out_err; -- --out_done: - mutex_unlock(&dev_priv->channel->mutex); - return 0; -- --out_err: -- nouveau_channel_put(&dev_priv->channel); -- return ret; - } - - static void nouveau_switcheroo_set_state(struct pci_dev *pdev, -@@ -646,6 +609,7 @@ nouveau_card_init(struct drm_device *dev) - spin_lock_init(&dev_priv->channels.lock); - spin_lock_init(&dev_priv->tile.lock); - spin_lock_init(&dev_priv->context_switch_lock); -+ spin_lock_init(&dev_priv->vm_lock); - - /* Make the CRTCs and I2C buses accessible */ - ret = engine->display.early_init(dev); -@@ -811,6 +775,11 @@ static void nouveau_card_takedown(struct drm_device *dev) - engine->mc.takedown(dev); - engine->display.late_takedown(dev); - -+ if (dev_priv->vga_ram) { -+ nouveau_bo_unpin(dev_priv->vga_ram); -+ nouveau_bo_ref(NULL, &dev_priv->vga_ram); -+ } -+ - mutex_lock(&dev->struct_mutex); - ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); - ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); -@@ -904,7 +873,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) - #ifdef CONFIG_X86 - primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; - #endif -- -+ - remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary); - return 0; - } -@@ -929,12 +898,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", - dev->pci_vendor, dev->pci_device, dev->pdev->class); - -- dev_priv->wq = create_workqueue("nouveau"); -- if (!dev_priv->wq) { -- ret = -EINVAL; -- goto err_priv; -- } -- - /* resource 0 is mmio regs */ - /* resource 1 is linear FB */ - /* resource 2 is RAMIN (mmio regs + 0x1000000) */ -@@ -947,7 +910,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - NV_ERROR(dev, "Unable to initialize the mmio mapping. " - "Please report your setup to " DRIVER_EMAIL "\n"); - ret = -EINVAL; -- goto err_wq; -+ goto err_priv; - } - NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", - (unsigned long long)mmio_start_offs); -@@ -962,11 +925,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) - - /* Time to determine the card architecture */ - reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); -+ dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */ - - /* We're dealing with >=NV10 */ - if ((reg0 & 0x0f000000) > 0) { - /* Bit 27-20 contain the architecture in hex */ - dev_priv->chipset = (reg0 & 0xff00000) >> 20; -+ dev_priv->stepping = (reg0 & 0xff); - /* NV04 or NV05 */ - } else if ((reg0 & 0xff00fff0) == 0x20004000) { - if (reg0 & 0x00f00000) -@@ -1054,8 +1019,6 @@ err_ramin: - iounmap(dev_priv->ramin); - err_mmio: - iounmap(dev_priv->mmio); --err_wq: -- destroy_workqueue(dev_priv->wq); - err_priv: - kfree(dev_priv); - dev->dev_private = NULL; -@@ -1126,7 +1089,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, - getparam->value = 1; - break; - case NOUVEAU_GETPARAM_HAS_PAGEFLIP: -- getparam->value = (dev_priv->card_type < NV_50); -+ getparam->value = 1; - break; - case NOUVEAU_GETPARAM_GRAPH_UNITS: - /* NV40 and NV50 versions are quite different, but register -diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c -index 8d9968e..649b041 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_temp.c -+++ b/drivers/gpu/drm/nouveau/nouveau_temp.c -@@ -239,11 +239,9 @@ static bool - probe_monitoring_device(struct nouveau_i2c_chan *i2c, - struct i2c_board_info *info) - { -- char modalias[16] = "i2c:"; - struct i2c_client *client; - -- strlcat(modalias, info->type, sizeof(modalias)); -- request_module(modalias); -+ request_module("%s%s", I2C_MODULE_PREFIX, info->type); - - client = i2c_new_device(&i2c->adapter, info); - if (!client) -diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c -index fbe0fb1..e51b515 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_util.c -+++ b/drivers/gpu/drm/nouveau/nouveau_util.c -@@ -47,18 +47,27 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) - printk(" (unknown bits 0x%08x)", value); - } - --void --nouveau_enum_print(const struct nouveau_enum *en, u32 value) -+const struct nouveau_enum * -+nouveau_enum_find(const struct nouveau_enum *en, u32 value) - { - while (en->name) { -- if (value == en->value) { -- printk("%s", en->name); -- return; -- } -- -+ if (en->value == value) -+ return en; - en++; - } - -+ return NULL; -+} -+ -+void -+nouveau_enum_print(const struct nouveau_enum *en, u32 value) -+{ -+ en = nouveau_enum_find(en, value); -+ if (en) { -+ printk("%s", en->name); -+ return; -+ } -+ - printk("(unknown enum 0x%08x)", value); - } - -diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h -index d9ceaea..b97719f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_util.h -+++ b/drivers/gpu/drm/nouveau/nouveau_util.h -@@ -36,10 +36,14 @@ struct nouveau_bitfield { - struct nouveau_enum { - u32 value; - const char *name; -+ void *data; - }; - - void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); - void nouveau_enum_print(const struct nouveau_enum *, u32 value); -+const struct nouveau_enum * -+nouveau_enum_find(const struct nouveau_enum *, u32 value); -+ - int nouveau_ratelimit(void); - - #endif -diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c -index 97d82ae..0059e6f 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_vm.c -+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c -@@ -28,7 +28,7 @@ - #include "nouveau_vm.h" - - void --nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) -+nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) - { - struct nouveau_vm *vm = vma->vm; - struct nouveau_mm_node *r; -@@ -40,7 +40,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) - u32 max = 1 << (vm->pgt_bits - bits); - u32 end, len; - -- list_for_each_entry(r, &vram->regions, rl_entry) { -+ delta = 0; -+ list_for_each_entry(r, &node->regions, rl_entry) { - u64 phys = (u64)r->offset << 12; - u32 num = r->length >> bits; - -@@ -52,7 +53,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) - end = max; - len = end - pte; - -- vm->map(vma, pgt, vram, pte, len, phys); -+ vm->map(vma, pgt, node, pte, len, phys, delta); - - num -= len; - pte += len; -@@ -60,6 +61,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) - pde++; - pte = 0; - } -+ -+ delta += (u64)len << vma->node->type; - } - } - -@@ -67,14 +70,14 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) - } - - void --nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram) -+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) - { -- nouveau_vm_map_at(vma, 0, vram); -+ nouveau_vm_map_at(vma, 0, node); - } - - void - nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, -- dma_addr_t *list) -+ struct nouveau_mem *mem, dma_addr_t *list) - { - struct nouveau_vm *vm = vma->vm; - int big = vma->node->type != vm->spg_shift; -@@ -94,7 +97,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, - end = max; - len = end - pte; - -- vm->map_sg(vma, pgt, pte, list, len); -+ vm->map_sg(vma, pgt, mem, pte, len, list); - - num -= len; - pte += len; -@@ -311,18 +314,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, - vm->spg_shift = 12; - vm->lpg_shift = 17; - pgt_bits = 27; -- -- /* Should be 4096 everywhere, this is a hack that's -- * currently necessary to avoid an elusive bug that -- * causes corruption when mixing small/large pages -- */ -- if (length < (1ULL << 40)) -- block = 4096; -- else { -- block = (1 << pgt_bits); -- if (length < block) -- block = length; -- } -+ block = 4096; - } else { - kfree(vm); - return -ENOSYS; -diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h -index e119351..2e06b55 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_vm.h -+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h -@@ -67,9 +67,10 @@ struct nouveau_vm { - void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]); - void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, -- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); -+ struct nouveau_mem *, u32 pte, u32 cnt, -+ u64 phys, u64 delta); - void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, -- u32 pte, dma_addr_t *, u32 cnt); -+ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); - void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); - void (*flush)(struct nouveau_vm *); - }; -@@ -82,20 +83,20 @@ int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, - int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, - u32 access, struct nouveau_vma *); - void nouveau_vm_put(struct nouveau_vma *); --void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *); --void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *); -+void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *); -+void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); - void nouveau_vm_unmap(struct nouveau_vma *); - void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); - void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, -- dma_addr_t *); -+ struct nouveau_mem *, dma_addr_t *); - - /* nv50_vm.c */ - void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]); - void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, -- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); -+ struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); - void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, -- u32 pte, dma_addr_t *, u32 cnt); -+ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); - void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); - void nv50_vm_flush(struct nouveau_vm *); - void nv50_vm_flush_engine(struct drm_device *, int engine); -@@ -104,9 +105,9 @@ void nv50_vm_flush_engine(struct drm_device *, int engine); - void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]); - void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, -- struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); -+ struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta); - void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, -- u32 pte, dma_addr_t *, u32 cnt); -+ struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); - void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); - void nvc0_vm_flush(struct nouveau_vm *); - -diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c -index 04fdc00..75e87274 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_volt.c -+++ b/drivers/gpu/drm/nouveau/nouveau_volt.c -@@ -159,8 +159,16 @@ nouveau_volt_init(struct drm_device *dev) - headerlen = volt[1]; - recordlen = volt[2]; - entries = volt[3]; -- vidshift = hweight8(volt[5]); - vidmask = volt[4]; -+ /* no longer certain what volt[5] is, if it's related to -+ * the vid shift then it's definitely not a function of -+ * how many bits are set. -+ * -+ * after looking at a number of nva3+ vbios images, they -+ * all seem likely to have a static shift of 2.. lets -+ * go with that for now until proven otherwise. -+ */ -+ vidshift = 2; - break; - default: - NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); -diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c -index 297505e..9eaafcc 100644 ---- a/drivers/gpu/drm/nouveau/nv04_crtc.c -+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c -@@ -376,7 +376,10 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) - */ - - /* framebuffer can be larger than crtc scanout area. */ -- regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); -+ regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = -+ XLATE(fb->pitch / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); -+ regp->CRTC[NV_CIO_CRE_42] = -+ XLATE(fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11); - regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->crtc_hdisplay < 1280 ? - MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00; - regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) | -@@ -790,8 +793,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, - if (atomic) { - drm_fb = passed_fb; - fb = nouveau_framebuffer(passed_fb); -- } -- else { -+ } else { - /* If not atomic, we can go ahead and pin, and unpin the - * old fb we were passed. - */ -@@ -825,8 +827,11 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, - regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = drm_fb->pitch >> 3; - regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = - XLATE(drm_fb->pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); -+ regp->CRTC[NV_CIO_CRE_42] = -+ XLATE(drm_fb->pitch / 8, 11, NV_CIO_CRE_42_OFFSET_11); - crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_RPC0_INDEX); - crtc_wr_cio_state(crtc, regp, NV_CIO_CR_OFFSET_INDEX); -+ crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_42); - - /* Update the framebuffer location. */ - regp->fb_start = nv_crtc->fb.offset & ~3; -@@ -944,14 +949,14 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, - struct drm_gem_object *gem; - int ret = 0; - -- if (width != 64 || height != 64) -- return -EINVAL; -- - if (!buffer_handle) { - nv_crtc->cursor.hide(nv_crtc, true); - return 0; - } - -+ if (width != 64 || height != 64) -+ return -EINVAL; -+ - gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); - if (!gem) - return -ENOENT; -@@ -1031,7 +1036,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) - drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); - - ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, -- 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); -+ 0, 0x0000, &nv_crtc->cursor.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); - if (!ret) -diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c -index c82db37..12098bf 100644 ---- a/drivers/gpu/drm/nouveau/nv04_dfp.c -+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c -@@ -581,12 +581,13 @@ static void nv04_dfp_restore(struct drm_encoder *encoder) - int head = nv_encoder->restore.head; - - if (nv_encoder->dcb->type == OUTPUT_LVDS) { -- struct drm_display_mode *native_mode = nouveau_encoder_connector_get(nv_encoder)->native_mode; -- if (native_mode) -- call_lvds_script(dev, nv_encoder->dcb, head, LVDS_PANEL_ON, -- native_mode->clock); -- else -- NV_ERROR(dev, "Not restoring LVDS without native mode\n"); -+ struct nouveau_connector *connector = -+ nouveau_encoder_connector_get(nv_encoder); -+ -+ if (connector && connector->native_mode) -+ call_lvds_script(dev, nv_encoder->dcb, head, -+ LVDS_PANEL_ON, -+ connector->native_mode->clock); - - } else if (nv_encoder->dcb->type == OUTPUT_TMDS) { - int clock = nouveau_hw_pllvals_to_clk -diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c -index f89d104..db465a3 100644 ---- a/drivers/gpu/drm/nouveau/nv04_fifo.c -+++ b/drivers/gpu/drm/nouveau/nv04_fifo.c -@@ -379,6 +379,15 @@ out: - return handled; - } - -+static const char *nv_dma_state_err(u32 state) -+{ -+ static const char * const desc[] = { -+ "NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE", -+ "INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK" -+ }; -+ return desc[(state >> 29) & 0x7]; -+} -+ - void - nv04_fifo_isr(struct drm_device *dev) - { -@@ -460,9 +469,10 @@ nv04_fifo_isr(struct drm_device *dev) - if (nouveau_ratelimit()) - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " - "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " -- "State 0x%08x Push 0x%08x\n", -+ "State 0x%08x (err: %s) Push 0x%08x\n", - chid, ho_get, dma_get, ho_put, - dma_put, ib_get, ib_put, state, -+ nv_dma_state_err(state), - push); - - /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ -@@ -476,8 +486,9 @@ nv04_fifo_isr(struct drm_device *dev) - } - } else { - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " -- "Put 0x%08x State 0x%08x Push 0x%08x\n", -- chid, dma_get, dma_put, state, push); -+ "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", -+ chid, dma_get, dma_put, state, -+ nv_dma_state_err(state), push); - - if (dma_get != dma_put) - nv_wr32(dev, 0x003244, dma_put); -@@ -505,7 +516,7 @@ nv04_fifo_isr(struct drm_device *dev) - - if (dev_priv->card_type == NV_50) { - if (status & 0x00000010) { -- nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); -+ nv50_fb_vm_trap(dev, nouveau_ratelimit()); - status &= ~0x00000010; - nv_wr32(dev, 0x002100, 0x00000010); - } -diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c -index af75015..055677a 100644 ---- a/drivers/gpu/drm/nouveau/nv04_graph.c -+++ b/drivers/gpu/drm/nouveau/nv04_graph.c -@@ -507,7 +507,7 @@ int nv04_graph_init(struct drm_device *dev) - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000); - /*1231C000 blob, 001 haiku*/ -- //*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ -+ /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ - nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100); - /*0x72111100 blob , 01 haiku*/ - /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ -@@ -1232,8 +1232,7 @@ static struct nouveau_bitfield nv04_graph_intr[] = { - {} - }; - --static struct nouveau_bitfield nv04_graph_nstatus[] = --{ -+static struct nouveau_bitfield nv04_graph_nstatus[] = { - { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, - { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, - { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, -@@ -1241,8 +1240,7 @@ static struct nouveau_bitfield nv04_graph_nstatus[] = - {} - }; - --struct nouveau_bitfield nv04_graph_nsource[] = --{ -+struct nouveau_bitfield nv04_graph_nsource[] = { - { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, - { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, - { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, -diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c -index b8e3edb..0671b7f 100644 ---- a/drivers/gpu/drm/nouveau/nv04_instmem.c -+++ b/drivers/gpu/drm/nouveau/nv04_instmem.c -@@ -95,6 +95,9 @@ nv04_instmem_takedown(struct drm_device *dev) - nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); - nouveau_gpuobj_ref(NULL, &dev_priv->ramro); - nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); -+ -+ if (dev_priv->ramin_heap.free_stack.next) -+ drm_mm_takedown(&dev_priv->ramin_heap); - } - - int -diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c -index 8c92edb..531d7ba 100644 ---- a/drivers/gpu/drm/nouveau/nv10_graph.c -+++ b/drivers/gpu/drm/nouveau/nv10_graph.c -@@ -1117,8 +1117,7 @@ struct nouveau_bitfield nv10_graph_intr[] = { - {} - }; - --struct nouveau_bitfield nv10_graph_nstatus[] = --{ -+struct nouveau_bitfield nv10_graph_nstatus[] = { - { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, - { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, - { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, -diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c -index f3d9c05..f0ac2a7 100644 ---- a/drivers/gpu/drm/nouveau/nv40_fb.c -+++ b/drivers/gpu/drm/nouveau/nv40_fb.c -@@ -24,6 +24,53 @@ nv40_fb_set_tile_region(struct drm_device *dev, int i) - } - } - -+static void -+nv40_fb_init_gart(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; -+ -+ if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { -+ nv_wr32(dev, 0x100800, 0x00000001); -+ return; -+ } -+ -+ nv_wr32(dev, 0x100800, gart->pinst | 0x00000002); -+ nv_mask(dev, 0x10008c, 0x00000100, 0x00000100); -+ nv_wr32(dev, 0x100820, 0x00000000); -+} -+ -+static void -+nv44_fb_init_gart(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma; -+ u32 vinst; -+ -+ if (dev_priv->gart_info.type != NOUVEAU_GART_HW) { -+ nv_wr32(dev, 0x100850, 0x80000000); -+ nv_wr32(dev, 0x100800, 0x00000001); -+ return; -+ } -+ -+ /* calculate vram address of this PRAMIN block, object -+ * must be allocated on 512KiB alignment, and not exceed -+ * a total size of 512KiB for this to work correctly -+ */ -+ vinst = nv_rd32(dev, 0x10020c); -+ vinst -= ((gart->pinst >> 19) + 1) << 19; -+ -+ nv_wr32(dev, 0x100850, 0x80000000); -+ nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr); -+ -+ nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size); -+ nv_wr32(dev, 0x100850, 0x00008000); -+ nv_mask(dev, 0x10008c, 0x00000200, 0x00000200); -+ nv_wr32(dev, 0x100820, 0x00000000); -+ nv_wr32(dev, 0x10082c, 0x00000001); -+ nv_wr32(dev, 0x100800, vinst | 0x00000010); -+} -+ - int - nv40_fb_init(struct drm_device *dev) - { -@@ -32,12 +79,12 @@ nv40_fb_init(struct drm_device *dev) - uint32_t tmp; - int i; - -- /* This is strictly a NV4x register (don't know about NV5x). */ -- /* The blob sets these to all kinds of values, and they mess up our setup. */ -- /* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */ -- /* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */ -- /* Any idea what this is? */ -- nv_wr32(dev, NV40_PFB_UNK_800, 0x1); -+ if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) { -+ if (nv44_graph_class(dev)) -+ nv44_fb_init_gart(dev); -+ else -+ nv40_fb_init_gart(dev); -+ } - - switch (dev_priv->chipset) { - case 0x40: -diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c -index de81151..8cf63a8 100644 ---- a/drivers/gpu/drm/nouveau/nv50_calc.c -+++ b/drivers/gpu/drm/nouveau/nv50_calc.c -@@ -23,7 +23,6 @@ - */ - - #include "drmP.h" --#include "drm_fixed.h" - #include "nouveau_drv.h" - #include "nouveau_hw.h" - -@@ -47,45 +46,52 @@ nv50_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, - } - - int --nv50_calc_pll2(struct drm_device *dev, struct pll_lims *pll, int clk, -- int *N, int *fN, int *M, int *P) -+nva3_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk, -+ int *pN, int *pfN, int *pM, int *P) - { -- fixed20_12 fb_div, a, b; -- u32 refclk = pll->refclk / 10; -- u32 max_vco_freq = pll->vco1.maxfreq / 10; -- u32 max_vco_inputfreq = pll->vco1.max_inputfreq / 10; -- clk /= 10; -+ u32 best_err = ~0, err; -+ int M, lM, hM, N, fN; - -- *P = max_vco_freq / clk; -+ *P = pll->vco1.maxfreq / clk; - if (*P > pll->max_p) - *P = pll->max_p; - if (*P < pll->min_p) - *P = pll->min_p; - -- /* *M = floor((refclk + max_vco_inputfreq) / max_vco_inputfreq); */ -- a.full = dfixed_const(refclk + max_vco_inputfreq); -- b.full = dfixed_const(max_vco_inputfreq); -- a.full = dfixed_div(a, b); -- a.full = dfixed_floor(a); -- *M = dfixed_trunc(a); -+ lM = (pll->refclk + pll->vco1.max_inputfreq) / pll->vco1.max_inputfreq; -+ lM = max(lM, (int)pll->vco1.min_m); -+ hM = (pll->refclk + pll->vco1.min_inputfreq) / pll->vco1.min_inputfreq; -+ hM = min(hM, (int)pll->vco1.max_m); - -- /* fb_div = (vco * *M) / refclk; */ -- fb_div.full = dfixed_const(clk * *P); -- fb_div.full = dfixed_mul(fb_div, a); -- a.full = dfixed_const(refclk); -- fb_div.full = dfixed_div(fb_div, a); -+ for (M = lM; M <= hM; M++) { -+ u32 tmp = clk * *P * M; -+ N = tmp / pll->refclk; -+ fN = tmp % pll->refclk; -+ if (!pfN && fN >= pll->refclk / 2) -+ N++; - -- /* *N = floor(fb_div); */ -- a.full = dfixed_floor(fb_div); -- *N = dfixed_trunc(fb_div); -+ if (N < pll->vco1.min_n) -+ continue; -+ if (N > pll->vco1.max_n) -+ break; - -- /* *fN = (fmod(fb_div, 1.0) * 8192) - 4096; */ -- b.full = dfixed_const(8192); -- a.full = dfixed_mul(a, b); -- fb_div.full = dfixed_mul(fb_div, b); -- fb_div.full = fb_div.full - a.full; -- *fN = dfixed_trunc(fb_div) - 4096; -- *fN &= 0xffff; -+ err = abs(clk - (pll->refclk * N / M / *P)); -+ if (err < best_err) { -+ best_err = err; -+ *pN = N; -+ *pM = M; -+ } - -- return clk; -+ if (pfN) { -+ *pfN = (((fN << 13) / pll->refclk) - 4096) & 0xffff; -+ return clk; -+ } -+ } -+ -+ if (unlikely(best_err == ~0)) { -+ NV_ERROR(dev, "unable to find matching pll values\n"); -+ return -EINVAL; -+ } -+ -+ return pll->refclk * *pN / *pM / *P; - } -diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c -index 9023c4d..ebabacf 100644 ---- a/drivers/gpu/drm/nouveau/nv50_crtc.c -+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c -@@ -65,7 +65,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) - { - struct drm_device *dev = nv_crtc->base.dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - int index = nv_crtc->index, ret; - - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); -@@ -135,8 +135,7 @@ static int - nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) - { - struct drm_device *dev = nv_crtc->base.dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - NV_DEBUG_KMS(dev, "\n"); -@@ -186,8 +185,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) - struct nouveau_connector *nv_connector = - nouveau_crtc_connector_get(nv_crtc); - struct drm_device *dev = nv_crtc->base.dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - struct drm_display_mode *native_mode = NULL; - struct drm_display_mode *mode = &nv_crtc->base.mode; - uint32_t outX, outY, horiz, vert; -@@ -288,7 +286,7 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) - nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); - } else - if (dev_priv->chipset < NV_C0) { -- ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); -+ ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); - if (ret <= 0) - return 0; - -@@ -300,7 +298,7 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) - nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); - nv_wr32(dev, pll.reg + 8, N2); - } else { -- ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); -+ ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P); - if (ret <= 0) - return 0; - -@@ -351,14 +349,14 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, - struct drm_gem_object *gem; - int ret = 0, i; - -- if (width != 64 || height != 64) -- return -EINVAL; -- - if (!buffer_handle) { - nv_crtc->cursor.hide(nv_crtc, true); - return 0; - } - -+ if (width != 64 || height != 64) -+ return -EINVAL; -+ - gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); - if (!gem) - return -ENOENT; -@@ -445,6 +443,39 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) - { - } - -+static int -+nv50_crtc_wait_complete(struct drm_crtc *crtc) -+{ -+ struct drm_device *dev = crtc->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -+ struct nv50_display *disp = nv50_display(dev); -+ struct nouveau_channel *evo = disp->master; -+ u64 start; -+ int ret; -+ -+ ret = RING_SPACE(evo, 6); -+ if (ret) -+ return ret; -+ BEGIN_RING(evo, 0, 0x0084, 1); -+ OUT_RING (evo, 0x80000000); -+ BEGIN_RING(evo, 0, 0x0080, 1); -+ OUT_RING (evo, 0); -+ BEGIN_RING(evo, 0, 0x0084, 1); -+ OUT_RING (evo, 0x00000000); -+ -+ nv_wo32(disp->ntfy, 0x000, 0x00000000); -+ FIRE_RING (evo); -+ -+ start = ptimer->read(dev); -+ do { -+ if (nv_ro32(disp->ntfy, 0x000)) -+ return 0; -+ } while (ptimer->read(dev) - start < 2000000000ULL); -+ -+ return -EBUSY; -+} -+ - static void - nv50_crtc_prepare(struct drm_crtc *crtc) - { -@@ -453,6 +484,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc) - - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - -+ nv50_display_flip_stop(crtc); - drm_vblank_pre_modeset(dev, nv_crtc->index); - nv50_crtc_blank(nv_crtc, true); - } -@@ -461,24 +493,14 @@ static void - nv50_crtc_commit(struct drm_crtc *crtc) - { - struct drm_device *dev = crtc->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -- int ret; - - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - - nv50_crtc_blank(nv_crtc, false); - drm_vblank_post_modeset(dev, nv_crtc->index); -- -- ret = RING_SPACE(evo, 2); -- if (ret) { -- NV_ERROR(dev, "no space while committing crtc\n"); -- return; -- } -- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); -- OUT_RING (evo, 0); -- FIRE_RING (evo); -+ nv50_crtc_wait_complete(crtc); -+ nv50_display_flip_next(crtc, crtc->fb, NULL); - } - - static bool -@@ -491,15 +513,15 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, - static int - nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, - struct drm_framebuffer *passed_fb, -- int x, int y, bool update, bool atomic) -+ int x, int y, bool atomic) - { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct drm_device *dev = nv_crtc->base.dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - struct drm_framebuffer *drm_fb = nv_crtc->base.fb; - struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); -- int ret, format; -+ int ret; - - NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - -@@ -510,8 +532,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, - if (atomic) { - drm_fb = passed_fb; - fb = nouveau_framebuffer(passed_fb); -- } -- else { -+ } else { - /* If not atomic, we can go ahead and pin, and unpin the - * old fb we were passed. - */ -@@ -525,28 +546,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, - } - } - -- switch (drm_fb->depth) { -- case 8: -- format = NV50_EVO_CRTC_FB_DEPTH_8; -- break; -- case 15: -- format = NV50_EVO_CRTC_FB_DEPTH_15; -- break; -- case 16: -- format = NV50_EVO_CRTC_FB_DEPTH_16; -- break; -- case 24: -- case 32: -- format = NV50_EVO_CRTC_FB_DEPTH_24; -- break; -- case 30: -- format = NV50_EVO_CRTC_FB_DEPTH_30; -- break; -- default: -- NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth); -- return -EINVAL; -- } -- - nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; - nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); - nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; -@@ -556,14 +555,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, - return ret; - - BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1); -- if (nv_crtc->fb.tile_flags == 0x7a00 || -- nv_crtc->fb.tile_flags == 0xfe00) -- OUT_RING(evo, NvEvoFB32); -- else -- if (nv_crtc->fb.tile_flags == 0x7000) -- OUT_RING(evo, NvEvoFB16); -- else -- OUT_RING(evo, NvEvoVRAM_LP); -+ OUT_RING (evo, fb->r_dma); - } - - ret = RING_SPACE(evo, 12); -@@ -571,45 +563,26 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, - return ret; - - BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5); -- OUT_RING(evo, nv_crtc->fb.offset >> 8); -- OUT_RING(evo, 0); -- OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width); -- if (!nv_crtc->fb.tile_flags) { -- OUT_RING(evo, drm_fb->pitch | (1 << 20)); -- } else { -- u32 tile_mode = fb->nvbo->tile_mode; -- if (dev_priv->card_type >= NV_C0) -- tile_mode >>= 4; -- OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode); -- } -- if (dev_priv->chipset == 0x50) -- OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); -- else -- OUT_RING(evo, format); -+ OUT_RING (evo, nv_crtc->fb.offset >> 8); -+ OUT_RING (evo, 0); -+ OUT_RING (evo, (drm_fb->height << 16) | drm_fb->width); -+ OUT_RING (evo, fb->r_pitch); -+ OUT_RING (evo, fb->r_format); - - BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1); -- OUT_RING(evo, fb->base.depth == 8 ? -- NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); -+ OUT_RING (evo, fb->base.depth == 8 ? -+ NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); - - BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1); -- OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); -+ OUT_RING (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR); - BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); -- OUT_RING(evo, (y << 16) | x); -+ OUT_RING (evo, (y << 16) | x); - - if (nv_crtc->lut.depth != fb->base.depth) { - nv_crtc->lut.depth = fb->base.depth; - nv50_crtc_lut_load(crtc); - } - -- if (update) { -- ret = RING_SPACE(evo, 2); -- if (ret) -- return ret; -- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); -- OUT_RING(evo, 0); -- FIRE_RING(evo); -- } -- - return 0; - } - -@@ -619,8 +592,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_framebuffer *old_fb) - { - struct drm_device *dev = crtc->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct nouveau_connector *nv_connector = NULL; - uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; -@@ -700,14 +672,25 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); - nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); - -- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false); -+ return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); - } - - static int - nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) - { -- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false); -+ int ret; -+ -+ nv50_display_flip_stop(crtc); -+ ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); -+ if (ret) -+ return ret; -+ -+ ret = nv50_crtc_wait_complete(crtc); -+ if (ret) -+ return ret; -+ -+ return nv50_display_flip_next(crtc, crtc->fb, NULL); - } - - static int -@@ -715,7 +698,14 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int x, int y, enum mode_set_atomic state) - { -- return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); -+ int ret; -+ -+ nv50_display_flip_stop(crtc); -+ ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true); -+ if (ret) -+ return ret; -+ -+ return nv50_crtc_wait_complete(crtc); - } - - static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { -@@ -758,7 +748,7 @@ nv50_crtc_create(struct drm_device *dev, int index) - nv_crtc->lut.depth = 0; - - ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, -- 0, 0x0000, false, true, &nv_crtc->lut.nvbo); -+ 0, 0x0000, &nv_crtc->lut.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); - if (!ret) -@@ -784,7 +774,7 @@ nv50_crtc_create(struct drm_device *dev, int index) - drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); - - ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, -- 0, 0x0000, false, true, &nv_crtc->cursor.nvbo); -+ 0, 0x0000, &nv_crtc->cursor.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); - if (!ret) -diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c -index 1b9ce30..9752c35 100644 ---- a/drivers/gpu/drm/nouveau/nv50_cursor.c -+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c -@@ -36,9 +36,9 @@ - static void - nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) - { -- struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; - struct drm_device *dev = nv_crtc->base.dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - NV_DEBUG_KMS(dev, "\n"); -@@ -71,9 +71,9 @@ nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) - static void - nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) - { -- struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; - struct drm_device *dev = nv_crtc->base.dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - NV_DEBUG_KMS(dev, "\n"); -diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c -index 875414b..808f3ec 100644 ---- a/drivers/gpu/drm/nouveau/nv50_dac.c -+++ b/drivers/gpu/drm/nouveau/nv50_dac.c -@@ -41,8 +41,7 @@ nv50_dac_disconnect(struct drm_encoder *encoder) - { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - if (!nv_encoder->crtc) -@@ -216,8 +215,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); - uint32_t mode_ctl = 0, mode_ctl2 = 0; - int ret; -diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c -index 7cc94ed..74a3f68 100644 ---- a/drivers/gpu/drm/nouveau/nv50_display.c -+++ b/drivers/gpu/drm/nouveau/nv50_display.c -@@ -24,6 +24,7 @@ - * - */ - -+#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) - #include "nv50_display.h" - #include "nouveau_crtc.h" - #include "nouveau_encoder.h" -@@ -34,6 +35,7 @@ - #include "drm_crtc_helper.h" - - static void nv50_display_isr(struct drm_device *); -+static void nv50_display_bh(unsigned long); - - static inline int - nv50_sor_nr(struct drm_device *dev) -@@ -172,16 +174,16 @@ nv50_display_init(struct drm_device *dev) - ret = nv50_evo_init(dev); - if (ret) - return ret; -- evo = dev_priv->evo; -+ evo = nv50_display(dev)->master; - - nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); - -- ret = RING_SPACE(evo, 11); -+ ret = RING_SPACE(evo, 15); - if (ret) - return ret; - BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); - OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); -- OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE); -+ OUT_RING(evo, NvEvoSync); - BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); - OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); - BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); -@@ -190,6 +192,11 @@ nv50_display_init(struct drm_device *dev) - OUT_RING(evo, 0); - BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); - OUT_RING(evo, 0); -+ /* required to make display sync channels not hate life */ -+ BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1); -+ OUT_RING (evo, 0x00000311); -+ BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1); -+ OUT_RING (evo, 0x00000311); - FIRE_RING(evo); - if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) - NV_ERROR(dev, "evo pushbuf stalled\n"); -@@ -201,6 +208,8 @@ nv50_display_init(struct drm_device *dev) - static int nv50_display_disable(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_display *disp = nv50_display(dev); -+ struct nouveau_channel *evo = disp->master; - struct drm_crtc *drm_crtc; - int ret, i; - -@@ -212,12 +221,12 @@ static int nv50_display_disable(struct drm_device *dev) - nv50_crtc_blank(crtc, true); - } - -- ret = RING_SPACE(dev_priv->evo, 2); -+ ret = RING_SPACE(evo, 2); - if (ret == 0) { -- BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1); -- OUT_RING(dev_priv->evo, 0); -+ BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); -+ OUT_RING(evo, 0); - } -- FIRE_RING(dev_priv->evo); -+ FIRE_RING(evo); - - /* Almost like ack'ing a vblank interrupt, maybe in the spirit of - * cleaning up? -@@ -267,10 +276,16 @@ int nv50_display_create(struct drm_device *dev) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; - struct drm_connector *connector, *ct; -+ struct nv50_display *priv; - int ret, i; - - NV_DEBUG_KMS(dev, "\n"); - -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ dev_priv->engine.display.priv = priv; -+ - /* init basic kernel modesetting */ - drm_mode_config_init(dev); - -@@ -330,7 +345,7 @@ int nv50_display_create(struct drm_device *dev) - } - } - -- INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); -+ tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); - nouveau_irq_register(dev, 26, nv50_display_isr); - - ret = nv50_display_init(dev); -@@ -345,12 +360,131 @@ int nv50_display_create(struct drm_device *dev) - void - nv50_display_destroy(struct drm_device *dev) - { -+ struct nv50_display *disp = nv50_display(dev); -+ - NV_DEBUG_KMS(dev, "\n"); - - drm_mode_config_cleanup(dev); - - nv50_display_disable(dev); - nouveau_irq_unregister(dev, 26); -+ kfree(disp); -+} -+ -+void -+nv50_display_flip_stop(struct drm_crtc *crtc) -+{ -+ struct nv50_display *disp = nv50_display(crtc->dev); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; -+ struct nouveau_channel *evo = dispc->sync; -+ int ret; -+ -+ ret = RING_SPACE(evo, 8); -+ if (ret) { -+ WARN_ON(1); -+ return; -+ } -+ -+ BEGIN_RING(evo, 0, 0x0084, 1); -+ OUT_RING (evo, 0x00000000); -+ BEGIN_RING(evo, 0, 0x0094, 1); -+ OUT_RING (evo, 0x00000000); -+ BEGIN_RING(evo, 0, 0x00c0, 1); -+ OUT_RING (evo, 0x00000000); -+ BEGIN_RING(evo, 0, 0x0080, 1); -+ OUT_RING (evo, 0x00000000); -+ FIRE_RING (evo); -+} -+ -+int -+nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, -+ struct nouveau_channel *chan) -+{ -+ struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; -+ struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); -+ struct nv50_display *disp = nv50_display(crtc->dev); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index]; -+ struct nouveau_channel *evo = dispc->sync; -+ int ret; -+ -+ ret = RING_SPACE(evo, 24); -+ if (unlikely(ret)) -+ return ret; -+ -+ /* synchronise with the rendering channel, if necessary */ -+ if (likely(chan)) { -+ u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset; -+ -+ ret = RING_SPACE(chan, 10); -+ if (ret) { -+ WIND_RING(evo); -+ return ret; -+ } -+ -+ if (dev_priv->chipset < 0xc0) { -+ BEGIN_RING(chan, NvSubSw, 0x0060, 2); -+ OUT_RING (chan, NvEvoSema0 + nv_crtc->index); -+ OUT_RING (chan, dispc->sem.offset); -+ BEGIN_RING(chan, NvSubSw, 0x006c, 1); -+ OUT_RING (chan, 0xf00d0000 | dispc->sem.value); -+ BEGIN_RING(chan, NvSubSw, 0x0064, 2); -+ OUT_RING (chan, dispc->sem.offset ^ 0x10); -+ OUT_RING (chan, 0x74b1e000); -+ BEGIN_RING(chan, NvSubSw, 0x0060, 1); -+ if (dev_priv->chipset < 0x84) -+ OUT_RING (chan, NvSema); -+ else -+ OUT_RING (chan, chan->vram_handle); -+ } else { -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); -+ OUT_RING (chan, upper_32_bits(offset)); -+ OUT_RING (chan, lower_32_bits(offset)); -+ OUT_RING (chan, 0xf00d0000 | dispc->sem.value); -+ OUT_RING (chan, 0x1002); -+ BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); -+ OUT_RING (chan, upper_32_bits(offset)); -+ OUT_RING (chan, lower_32_bits(offset ^ 0x10)); -+ OUT_RING (chan, 0x74b1e000); -+ OUT_RING (chan, 0x1001); -+ } -+ FIRE_RING (chan); -+ } else { -+ nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4, -+ 0xf00d0000 | dispc->sem.value); -+ } -+ -+ /* queue the flip on the crtc's "display sync" channel */ -+ BEGIN_RING(evo, 0, 0x0100, 1); -+ OUT_RING (evo, 0xfffe0000); -+ BEGIN_RING(evo, 0, 0x0084, 5); -+ OUT_RING (evo, chan ? 0x00000100 : 0x00000010); -+ OUT_RING (evo, dispc->sem.offset); -+ OUT_RING (evo, 0xf00d0000 | dispc->sem.value); -+ OUT_RING (evo, 0x74b1e000); -+ OUT_RING (evo, NvEvoSync); -+ BEGIN_RING(evo, 0, 0x00a0, 2); -+ OUT_RING (evo, 0x00000000); -+ OUT_RING (evo, 0x00000000); -+ BEGIN_RING(evo, 0, 0x00c0, 1); -+ OUT_RING (evo, nv_fb->r_dma); -+ BEGIN_RING(evo, 0, 0x0110, 2); -+ OUT_RING (evo, 0x00000000); -+ OUT_RING (evo, 0x00000000); -+ BEGIN_RING(evo, 0, 0x0800, 5); -+ OUT_RING (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8); -+ OUT_RING (evo, 0); -+ OUT_RING (evo, (fb->height << 16) | fb->width); -+ OUT_RING (evo, nv_fb->r_pitch); -+ OUT_RING (evo, nv_fb->r_format); -+ BEGIN_RING(evo, 0, 0x0080, 1); -+ OUT_RING (evo, 0x00000000); -+ FIRE_RING (evo); -+ -+ dispc->sem.offset ^= 0x10; -+ dispc->sem.value++; -+ return 0; - } - - static u16 -@@ -383,13 +517,25 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, - if (bios->fp.if_is_24bit) - script |= 0x0200; - } else { -+ /* determine number of lvds links */ -+ if (nv_connector && nv_connector->edid && -+ nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { -+ /* http://www.spwg.org */ -+ if (((u8 *)nv_connector->edid)[121] == 2) -+ script |= 0x0100; -+ } else - if (pxclk >= bios->fp.duallink_transition_clk) { - script |= 0x0100; -+ } -+ -+ /* determine panel depth */ -+ if (script & 0x0100) { - if (bios->fp.strapless_is_24bit & 2) - script |= 0x0200; -- } else -- if (bios->fp.strapless_is_24bit & 1) -- script |= 0x0200; -+ } else { -+ if (bios->fp.strapless_is_24bit & 1) -+ script |= 0x0200; -+ } - - if (nv_connector && nv_connector->edid && - (nv_connector->edid->revision >= 4) && -@@ -466,11 +612,12 @@ static void - nv50_display_unk10_handler(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_display *disp = nv50_display(dev); - u32 unk30 = nv_rd32(dev, 0x610030), mc; - int i, crtc, or, type = OUTPUT_ANY; - - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); -- dev_priv->evo_irq.dcb = NULL; -+ disp->irq.dcb = NULL; - - nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); - -@@ -541,7 +688,7 @@ nv50_display_unk10_handler(struct drm_device *dev) - - if (dcb->type == type && (dcb->or & (1 << or))) { - nouveau_bios_run_display_table(dev, dcb, 0, -1); -- dev_priv->evo_irq.dcb = dcb; -+ disp->irq.dcb = dcb; - goto ack; - } - } -@@ -587,15 +734,16 @@ static void - nv50_display_unk20_handler(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc; -+ struct nv50_display *disp = nv50_display(dev); -+ u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; - struct dcb_entry *dcb; - int i, crtc, or, type = OUTPUT_ANY; - - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); -- dcb = dev_priv->evo_irq.dcb; -+ dcb = disp->irq.dcb; - if (dcb) { - nouveau_bios_run_display_table(dev, dcb, 0, -2); -- dev_priv->evo_irq.dcb = NULL; -+ disp->irq.dcb = NULL; - } - - /* CRTC clock change requested? */ -@@ -692,9 +840,9 @@ nv50_display_unk20_handler(struct drm_device *dev) - nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); - } - -- dev_priv->evo_irq.dcb = dcb; -- dev_priv->evo_irq.pclk = pclk; -- dev_priv->evo_irq.script = script; -+ disp->irq.dcb = dcb; -+ disp->irq.pclk = pclk; -+ disp->irq.script = script; - - ack: - nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); -@@ -735,13 +883,13 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb) - static void - nv50_display_unk40_handler(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct dcb_entry *dcb = dev_priv->evo_irq.dcb; -- u16 script = dev_priv->evo_irq.script; -- u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk; -+ struct nv50_display *disp = nv50_display(dev); -+ struct dcb_entry *dcb = disp->irq.dcb; -+ u16 script = disp->irq.script; -+ u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk; - - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); -- dev_priv->evo_irq.dcb = NULL; -+ disp->irq.dcb = NULL; - if (!dcb) - goto ack; - -@@ -754,12 +902,10 @@ ack: - nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); - } - --void --nv50_display_irq_handler_bh(struct work_struct *work) -+static void -+nv50_display_bh(unsigned long data) - { -- struct drm_nouveau_private *dev_priv = -- container_of(work, struct drm_nouveau_private, irq_work); -- struct drm_device *dev = dev_priv->dev; -+ struct drm_device *dev = (struct drm_device *)data; - - for (;;) { - uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); -@@ -807,7 +953,7 @@ nv50_display_error_handler(struct drm_device *dev) - static void - nv50_display_isr(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_display *disp = nv50_display(dev); - uint32_t delayed = 0; - - while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { -@@ -835,8 +981,7 @@ nv50_display_isr(struct drm_device *dev) - NV50_PDISPLAY_INTR_1_CLK_UNK40)); - if (clock) { - nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); -- if (!work_pending(&dev_priv->irq_work)) -- queue_work(dev_priv->wq, &dev_priv->irq_work); -+ tasklet_schedule(&disp->tasklet); - delayed |= clock; - intr1 &= ~clock; - } -diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h -index f0e30b78..c2da503 100644 ---- a/drivers/gpu/drm/nouveau/nv50_display.h -+++ b/drivers/gpu/drm/nouveau/nv50_display.h -@@ -35,7 +35,36 @@ - #include "nouveau_crtc.h" - #include "nv50_evo.h" - --void nv50_display_irq_handler_bh(struct work_struct *work); -+struct nv50_display_crtc { -+ struct nouveau_channel *sync; -+ struct { -+ struct nouveau_bo *bo; -+ u32 offset; -+ u16 value; -+ } sem; -+}; -+ -+struct nv50_display { -+ struct nouveau_channel *master; -+ struct nouveau_gpuobj *ntfy; -+ -+ struct nv50_display_crtc crtc[2]; -+ -+ struct tasklet_struct tasklet; -+ struct { -+ struct dcb_entry *dcb; -+ u16 script; -+ u32 pclk; -+ } irq; -+}; -+ -+static inline struct nv50_display * -+nv50_display(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ return dev_priv->engine.display.priv; -+} -+ - int nv50_display_early_init(struct drm_device *dev); - void nv50_display_late_takedown(struct drm_device *dev); - int nv50_display_create(struct drm_device *dev); -@@ -44,4 +73,15 @@ void nv50_display_destroy(struct drm_device *dev); - int nv50_crtc_blank(struct nouveau_crtc *, bool blank); - int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); - -+int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, -+ struct nouveau_channel *chan); -+void nv50_display_flip_stop(struct drm_crtc *); -+ -+int nv50_evo_init(struct drm_device *dev); -+void nv50_evo_fini(struct drm_device *dev); -+void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, -+ u64 size); -+int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, -+ u64 base, u64 size, struct nouveau_gpuobj **); -+ - #endif /* __NV50_DISPLAY_H__ */ -diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c -index 0ea090f..c8e83c1 100644 ---- a/drivers/gpu/drm/nouveau/nv50_evo.c -+++ b/drivers/gpu/drm/nouveau/nv50_evo.c -@@ -27,20 +27,17 @@ - #include "nouveau_drv.h" - #include "nouveau_dma.h" - #include "nouveau_ramht.h" -+#include "nv50_display.h" - - static void - nv50_evo_channel_del(struct nouveau_channel **pevo) - { -- struct drm_nouveau_private *dev_priv; - struct nouveau_channel *evo = *pevo; - - if (!evo) - return; - *pevo = NULL; - -- dev_priv = evo->dev->dev_private; -- dev_priv->evo_alloc &= ~(1 << evo->id); -- - nouveau_gpuobj_channel_takedown(evo); - nouveau_bo_unmap(evo->pushbuf_bo); - nouveau_bo_ref(NULL, &evo->pushbuf_bo); -@@ -51,42 +48,61 @@ nv50_evo_channel_del(struct nouveau_channel **pevo) - kfree(evo); - } - -+void -+nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size) -+{ -+ struct drm_nouveau_private *dev_priv = obj->dev->dev_private; -+ u32 flags5; -+ -+ if (dev_priv->chipset < 0xc0) { -+ /* not supported on 0x50, specified in format mthd */ -+ if (dev_priv->chipset == 0x50) -+ memtype = 0; -+ flags5 = 0x00010000; -+ } else { -+ if (memtype & 0x80000000) -+ flags5 = 0x00000000; /* large pages */ -+ else -+ flags5 = 0x00020000; -+ } -+ -+ nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM, -+ NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0); -+ nv_wo32(obj, 0x14, flags5); -+ dev_priv->engine.instmem.flush(obj->dev); -+} -+ - int --nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, -- u32 tile_flags, u32 magic_flags, u32 offset, u32 limit, -- u32 flags5) -+nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, -+ u64 base, u64 size, struct nouveau_gpuobj **pobj) - { -- struct drm_nouveau_private *dev_priv = evo->dev->dev_private; -- struct drm_device *dev = evo->dev; -+ struct nv50_display *disp = nv50_display(evo->dev); - struct nouveau_gpuobj *obj = NULL; - int ret; - -- ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); -+ ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj); - if (ret) - return ret; - obj->engine = NVOBJ_ENGINE_DISPLAY; - -- nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); -- nv_wo32(obj, 4, limit); -- nv_wo32(obj, 8, offset); -- nv_wo32(obj, 12, 0x00000000); -- nv_wo32(obj, 16, 0x00000000); -- nv_wo32(obj, 20, flags5); -- dev_priv->engine.instmem.flush(dev); -+ nv50_evo_dmaobj_init(obj, memtype, base, size); - -- ret = nouveau_ramht_insert(evo, name, obj); -- nouveau_gpuobj_ref(NULL, &obj); -- if (ret) { -- return ret; -- } -+ ret = nouveau_ramht_insert(evo, handle, obj); -+ if (ret) -+ goto out; - -- return 0; -+ if (pobj) -+ nouveau_gpuobj_ref(obj, pobj); -+out: -+ nouveau_gpuobj_ref(NULL, &obj); -+ return ret; - } - - static int --nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) -+nv50_evo_channel_new(struct drm_device *dev, int chid, -+ struct nouveau_channel **pevo) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_display *disp = nv50_display(dev); - struct nouveau_channel *evo; - int ret; - -@@ -95,25 +111,13 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) - return -ENOMEM; - *pevo = evo; - -- for (evo->id = 0; evo->id < 5; evo->id++) { -- if (dev_priv->evo_alloc & (1 << evo->id)) -- continue; -- -- dev_priv->evo_alloc |= (1 << evo->id); -- break; -- } -- -- if (evo->id == 5) { -- kfree(evo); -- return -ENODEV; -- } -- -+ evo->id = chid; - evo->dev = dev; - evo->user_get = 4; - evo->user_put = 0; - - ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, -- false, true, &evo->pushbuf_bo); -+ &evo->pushbuf_bo); - if (ret == 0) - ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); - if (ret) { -@@ -138,8 +142,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) - } - - /* bind primary evo channel's ramht to the channel */ -- if (dev_priv->evo && evo != dev_priv->evo) -- nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); -+ if (disp->master && evo != disp->master) -+ nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL); - - return 0; - } -@@ -182,6 +186,7 @@ nv50_evo_channel_init(struct nouveau_channel *evo) - nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); - - evo->dma.max = (4096/4) - 2; -+ evo->dma.max &= ~7; - evo->dma.put = 0; - evo->dma.cur = evo->dma.put; - evo->dma.free = evo->dma.max - evo->dma.cur; -@@ -212,21 +217,39 @@ nv50_evo_channel_fini(struct nouveau_channel *evo) - } - } - -+static void -+nv50_evo_destroy(struct drm_device *dev) -+{ -+ struct nv50_display *disp = nv50_display(dev); -+ int i; -+ -+ for (i = 0; i < 2; i++) { -+ if (disp->crtc[i].sem.bo) { -+ nouveau_bo_unmap(disp->crtc[i].sem.bo); -+ nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo); -+ } -+ nv50_evo_channel_del(&disp->crtc[i].sync); -+ } -+ nouveau_gpuobj_ref(NULL, &disp->ntfy); -+ nv50_evo_channel_del(&disp->master); -+} -+ - static int - nv50_evo_create(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_display *disp = nv50_display(dev); - struct nouveau_gpuobj *ramht = NULL; - struct nouveau_channel *evo; -- int ret; -+ int ret, i, j; - - /* create primary evo channel, the one we use for modesetting - * purporses - */ -- ret = nv50_evo_channel_new(dev, &dev_priv->evo); -+ ret = nv50_evo_channel_new(dev, 0, &disp->master); - if (ret) - return ret; -- evo = dev_priv->evo; -+ evo = disp->master; - - /* setup object management on it, any other evo channel will - * use this also as there's no per-channel support on the -@@ -236,109 +259,167 @@ nv50_evo_create(struct drm_device *dev) - NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); - if (ret) { - NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -+ goto err; - } - - ret = drm_mm_init(&evo->ramin_heap, 0, 32768); - if (ret) { - NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -+ goto err; - } - - ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); - if (ret) { - NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -+ goto err; - } - - ret = nouveau_ramht_new(dev, ramht, &evo->ramht); - nouveau_gpuobj_ref(NULL, &ramht); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -- } -+ if (ret) -+ goto err; -+ -+ /* not sure exactly what this is.. -+ * -+ * the first dword of the structure is used by nvidia to wait on -+ * full completion of an EVO "update" command. -+ * -+ * method 0x8c on the master evo channel will fill a lot more of -+ * this structure with some undefined info -+ */ -+ ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0, -+ NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy); -+ if (ret) -+ goto err; -+ -+ ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000, -+ disp->ntfy->vinst, disp->ntfy->size, NULL); -+ if (ret) -+ goto err; - - /* create some default objects for the scanout memtypes we support */ -- if (dev_priv->card_type >= NV_C0) { -- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19, -- 0, 0xffffffff, 0x00000000); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -- } -+ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, -+ 0, dev_priv->vram_size, NULL); -+ if (ret) -+ goto err; - -- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, -- 0, dev_priv->vram_size, 0x00020000); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -- } -+ ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, -+ 0, dev_priv->vram_size, NULL); -+ if (ret) -+ goto err; - -- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, -- 0, dev_priv->vram_size, 0x00000000); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -- } -- } else { -- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, -- 0, 0xffffffff, 0x00010000); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -- } -+ ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | -+ (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00), -+ 0, dev_priv->vram_size, NULL); -+ if (ret) -+ goto err; - -+ ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | -+ (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00), -+ 0, dev_priv->vram_size, NULL); -+ if (ret) -+ goto err; - -- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, -- 0, 0xffffffff, 0x00010000); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -- } -+ /* create "display sync" channels and other structures we need -+ * to implement page flipping -+ */ -+ for (i = 0; i < 2; i++) { -+ struct nv50_display_crtc *dispc = &disp->crtc[i]; -+ u64 offset; - -- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, -- 0, dev_priv->vram_size, 0x00010000); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -+ ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync); -+ if (ret) -+ goto err; -+ -+ ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM, -+ 0, 0x0000, &dispc->sem.bo); -+ if (!ret) { -+ offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; -+ -+ ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); -+ if (!ret) -+ ret = nouveau_bo_map(dispc->sem.bo); -+ if (ret) -+ nouveau_bo_ref(NULL, &dispc->sem.bo); - } - -- ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19, -- 0, dev_priv->vram_size, 0x00010000); -- if (ret) { -- nv50_evo_channel_del(&dev_priv->evo); -- return ret; -- } -+ if (ret) -+ goto err; -+ -+ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000, -+ offset, 4096, NULL); -+ if (ret) -+ goto err; -+ -+ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, -+ 0, dev_priv->vram_size, NULL); -+ if (ret) -+ goto err; -+ -+ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | -+ (dev_priv->chipset < 0xc0 ? -+ 0x7a00 : 0xfe00), -+ 0, dev_priv->vram_size, NULL); -+ if (ret) -+ goto err; -+ -+ ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | -+ (dev_priv->chipset < 0xc0 ? -+ 0x7000 : 0xfe00), -+ 0, dev_priv->vram_size, NULL); -+ if (ret) -+ goto err; -+ -+ for (j = 0; j < 4096; j += 4) -+ nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000); -+ dispc->sem.offset = 0; - } - - return 0; -+ -+err: -+ nv50_evo_destroy(dev); -+ return ret; - } - - int - nv50_evo_init(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- int ret; -+ struct nv50_display *disp = nv50_display(dev); -+ int ret, i; - -- if (!dev_priv->evo) { -+ if (!disp->master) { - ret = nv50_evo_create(dev); - if (ret) - return ret; - } - -- return nv50_evo_channel_init(dev_priv->evo); -+ ret = nv50_evo_channel_init(disp->master); -+ if (ret) -+ return ret; -+ -+ for (i = 0; i < 2; i++) { -+ ret = nv50_evo_channel_init(disp->crtc[i].sync); -+ if (ret) -+ return ret; -+ } -+ -+ return 0; - } - - void - nv50_evo_fini(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv50_display *disp = nv50_display(dev); -+ int i; - -- if (dev_priv->evo) { -- nv50_evo_channel_fini(dev_priv->evo); -- nv50_evo_channel_del(&dev_priv->evo); -+ for (i = 0; i < 2; i++) { -+ if (disp->crtc[i].sync) -+ nv50_evo_channel_fini(disp->crtc[i].sync); - } -+ -+ if (disp->master) -+ nv50_evo_channel_fini(disp->master); -+ -+ nv50_evo_destroy(dev); - } -diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h -index aa4f0d3..3860ca6 100644 ---- a/drivers/gpu/drm/nouveau/nv50_evo.h -+++ b/drivers/gpu/drm/nouveau/nv50_evo.h -@@ -27,12 +27,6 @@ - #ifndef __NV50_EVO_H__ - #define __NV50_EVO_H__ - --int nv50_evo_init(struct drm_device *dev); --void nv50_evo_fini(struct drm_device *dev); --int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, -- u32 tile_flags, u32 magic_flags, -- u32 offset, u32 limit); -- - #define NV50_EVO_UPDATE 0x00000080 - #define NV50_EVO_UNK84 0x00000084 - #define NV50_EVO_UNK84_NOTIFY 0x40000000 -@@ -119,5 +113,7 @@ int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, - /* Both of these are needed, otherwise nothing happens. */ - #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 - #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc -+#define NV50_EVO_CRTC_UNK900 0x00000900 -+#define NV50_EVO_CRTC_UNK904 0x00000904 - - #endif -diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c -index 50290de..ddebd71 100644 ---- a/drivers/gpu/drm/nouveau/nv50_fb.c -+++ b/drivers/gpu/drm/nouveau/nv50_fb.c -@@ -8,31 +8,61 @@ struct nv50_fb_priv { - dma_addr_t r100c08; - }; - -+static void -+nv50_fb_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ struct nv50_fb_priv *priv = pfb->priv; -+ -+ if (pfb->tag_heap.free_stack.next) -+ drm_mm_takedown(&pfb->tag_heap); -+ -+ if (priv->r100c08_page) { -+ pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, -+ PCI_DMA_BIDIRECTIONAL); -+ __free_page(priv->r100c08_page); -+ } -+ -+ kfree(priv); -+ pfb->priv = NULL; -+} -+ - static int - nv50_fb_create(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nv50_fb_priv *priv; -+ u32 tagmem; -+ int ret; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; -+ pfb->priv = priv; - - priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!priv->r100c08_page) { -- kfree(priv); -+ nv50_fb_destroy(dev); - return -ENOMEM; - } - - priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { -- __free_page(priv->r100c08_page); -- kfree(priv); -+ nv50_fb_destroy(dev); - return -EFAULT; - } - -- dev_priv->engine.fb.priv = priv; -+ tagmem = nv_rd32(dev, 0x100320); -+ NV_DEBUG(dev, "%d tags available\n", tagmem); -+ ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); -+ if (ret) { -+ nv50_fb_destroy(dev); -+ return ret; -+ } -+ - return 0; - } - -@@ -81,26 +111,112 @@ nv50_fb_init(struct drm_device *dev) - void - nv50_fb_takedown(struct drm_device *dev) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv50_fb_priv *priv; -+ nv50_fb_destroy(dev); -+} - -- priv = dev_priv->engine.fb.priv; -- if (!priv) -- return; -- dev_priv->engine.fb.priv = NULL; -+static struct nouveau_enum vm_dispatch_subclients[] = { -+ { 0x00000000, "GRCTX", NULL }, -+ { 0x00000001, "NOTIFY", NULL }, -+ { 0x00000002, "QUERY", NULL }, -+ { 0x00000003, "COND", NULL }, -+ { 0x00000004, "M2M_IN", NULL }, -+ { 0x00000005, "M2M_OUT", NULL }, -+ { 0x00000006, "M2M_NOTIFY", NULL }, -+ {} -+}; - -- pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, -- PCI_DMA_BIDIRECTIONAL); -- __free_page(priv->r100c08_page); -- kfree(priv); --} -+static struct nouveau_enum vm_ccache_subclients[] = { -+ { 0x00000000, "CB", NULL }, -+ { 0x00000001, "TIC", NULL }, -+ { 0x00000002, "TSC", NULL }, -+ {} -+}; -+ -+static struct nouveau_enum vm_prop_subclients[] = { -+ { 0x00000000, "RT0", NULL }, -+ { 0x00000001, "RT1", NULL }, -+ { 0x00000002, "RT2", NULL }, -+ { 0x00000003, "RT3", NULL }, -+ { 0x00000004, "RT4", NULL }, -+ { 0x00000005, "RT5", NULL }, -+ { 0x00000006, "RT6", NULL }, -+ { 0x00000007, "RT7", NULL }, -+ { 0x00000008, "ZETA", NULL }, -+ { 0x00000009, "LOCAL", NULL }, -+ { 0x0000000a, "GLOBAL", NULL }, -+ { 0x0000000b, "STACK", NULL }, -+ { 0x0000000c, "DST2D", NULL }, -+ {} -+}; -+ -+static struct nouveau_enum vm_pfifo_subclients[] = { -+ { 0x00000000, "PUSHBUF", NULL }, -+ { 0x00000001, "SEMAPHORE", NULL }, -+ {} -+}; -+ -+static struct nouveau_enum vm_bar_subclients[] = { -+ { 0x00000000, "FB", NULL }, -+ { 0x00000001, "IN", NULL }, -+ {} -+}; -+ -+static struct nouveau_enum vm_client[] = { -+ { 0x00000000, "STRMOUT", NULL }, -+ { 0x00000003, "DISPATCH", vm_dispatch_subclients }, -+ { 0x00000004, "PFIFO_WRITE", NULL }, -+ { 0x00000005, "CCACHE", vm_ccache_subclients }, -+ { 0x00000006, "PPPP", NULL }, -+ { 0x00000007, "CLIPID", NULL }, -+ { 0x00000008, "PFIFO_READ", NULL }, -+ { 0x00000009, "VFETCH", NULL }, -+ { 0x0000000a, "TEXTURE", NULL }, -+ { 0x0000000b, "PROP", vm_prop_subclients }, -+ { 0x0000000c, "PVP", NULL }, -+ { 0x0000000d, "PBSP", NULL }, -+ { 0x0000000e, "PCRYPT", NULL }, -+ { 0x0000000f, "PCOUNTER", NULL }, -+ { 0x00000011, "PDAEMON", NULL }, -+ {} -+}; -+ -+static struct nouveau_enum vm_engine[] = { -+ { 0x00000000, "PGRAPH", NULL }, -+ { 0x00000001, "PVP", NULL }, -+ { 0x00000004, "PEEPHOLE", NULL }, -+ { 0x00000005, "PFIFO", vm_pfifo_subclients }, -+ { 0x00000006, "BAR", vm_bar_subclients }, -+ { 0x00000008, "PPPP", NULL }, -+ { 0x00000009, "PBSP", NULL }, -+ { 0x0000000a, "PCRYPT", NULL }, -+ { 0x0000000b, "PCOUNTER", NULL }, -+ { 0x0000000c, "SEMAPHORE_BG", NULL }, -+ { 0x0000000d, "PCOPY", NULL }, -+ { 0x0000000e, "PDAEMON", NULL }, -+ {} -+}; -+ -+static struct nouveau_enum vm_fault[] = { -+ { 0x00000000, "PT_NOT_PRESENT", NULL }, -+ { 0x00000001, "PT_TOO_SHORT", NULL }, -+ { 0x00000002, "PAGE_NOT_PRESENT", NULL }, -+ { 0x00000003, "PAGE_SYSTEM_ONLY", NULL }, -+ { 0x00000004, "PAGE_READ_ONLY", NULL }, -+ { 0x00000006, "NULL_DMAOBJ", NULL }, -+ { 0x00000007, "WRONG_MEMTYPE", NULL }, -+ { 0x0000000b, "VRAM_LIMIT", NULL }, -+ { 0x0000000f, "DMAOBJ_LIMIT", NULL }, -+ {} -+}; - - void --nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) -+nv50_fb_vm_trap(struct drm_device *dev, int display) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ const struct nouveau_enum *en, *cl; - unsigned long flags; - u32 trap[6], idx, chinst; -+ u8 st0, st1, st2, st3; - int i, ch; - - idx = nv_rd32(dev, 0x100c90); -@@ -117,8 +233,8 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) - if (!display) - return; - -+ /* lookup channel id */ - chinst = (trap[2] << 16) | trap[1]; -- - spin_lock_irqsave(&dev_priv->channels.lock, flags); - for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { - struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; -@@ -131,9 +247,48 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) - } - spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - -- NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " -- "channel %d (0x%08x)\n", -- name, (trap[5] & 0x100 ? "read" : "write"), -- trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, -- trap[0], ch, chinst); -+ /* decode status bits into something more useful */ -+ if (dev_priv->chipset < 0xa3 || -+ dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { -+ st0 = (trap[0] & 0x0000000f) >> 0; -+ st1 = (trap[0] & 0x000000f0) >> 4; -+ st2 = (trap[0] & 0x00000f00) >> 8; -+ st3 = (trap[0] & 0x0000f000) >> 12; -+ } else { -+ st0 = (trap[0] & 0x000000ff) >> 0; -+ st1 = (trap[0] & 0x0000ff00) >> 8; -+ st2 = (trap[0] & 0x00ff0000) >> 16; -+ st3 = (trap[0] & 0xff000000) >> 24; -+ } -+ -+ NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ", -+ (trap[5] & 0x00000100) ? "read" : "write", -+ trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst); -+ -+ en = nouveau_enum_find(vm_engine, st0); -+ if (en) -+ printk("%s/", en->name); -+ else -+ printk("%02x/", st0); -+ -+ cl = nouveau_enum_find(vm_client, st2); -+ if (cl) -+ printk("%s/", cl->name); -+ else -+ printk("%02x/", st2); -+ -+ if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3); -+ else if (en && en->data) cl = nouveau_enum_find(en->data, st3); -+ else cl = NULL; -+ if (cl) -+ printk("%s", cl->name); -+ else -+ printk("%02x", st3); -+ -+ printk(" reason: "); -+ en = nouveau_enum_find(vm_fault, st1); -+ if (en) -+ printk("%s\n", en->name); -+ else -+ printk("0x%08x\n", st1); - } -diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c -index 8dd04c5..c34a074 100644 ---- a/drivers/gpu/drm/nouveau/nv50_fifo.c -+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c -@@ -149,6 +149,7 @@ nv50_fifo_init_regs(struct drm_device *dev) - nv_wr32(dev, 0x3204, 0); - nv_wr32(dev, 0x3210, 0); - nv_wr32(dev, 0x3270, 0); -+ nv_wr32(dev, 0x2044, 0x01003fff); - - /* Enable dummy channels setup by nv50_instmem.c */ - nv50_fifo_channel_enable(dev, 0); -@@ -273,7 +274,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) - nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) | - (4 << 24) /* SEARCH_FULL */ | - (chan->ramht->gpuobj->cinst >> 4)); -- nv_wo32(ramfc, 0x44, 0x2101ffff); -+ nv_wo32(ramfc, 0x44, 0x01003fff); - nv_wo32(ramfc, 0x60, 0x7fffffff); - nv_wo32(ramfc, 0x40, 0x00000000); - nv_wo32(ramfc, 0x7c, 0x30000001); -diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c -index 6b149c0..d4f4206 100644 ---- a/drivers/gpu/drm/nouveau/nv50_gpio.c -+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c -@@ -137,6 +137,7 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, - struct nv50_gpio_priv *priv = pgpio->priv; - struct nv50_gpio_handler *gpioh, *tmp; - struct dcb_gpio_entry *gpio; -+ LIST_HEAD(tofree); - unsigned long flags; - - gpio = nouveau_bios_gpio_entry(dev, tag); -@@ -149,10 +150,14 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, - gpioh->handler != handler || - gpioh->data != data) - continue; -- list_del(&gpioh->head); -- kfree(gpioh); -+ list_move(&gpioh->head, &tofree); - } - spin_unlock_irqrestore(&priv->lock, flags); -+ -+ list_for_each_entry_safe(gpioh, tmp, &tofree, head) { -+ flush_work_sync(&gpioh->work); -+ kfree(gpioh); -+ } - } - - bool -@@ -205,7 +210,6 @@ nv50_gpio_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- struct nv50_gpio_priv *priv; - int ret; - - if (!pgpio->priv) { -@@ -213,7 +217,6 @@ nv50_gpio_init(struct drm_device *dev) - if (ret) - return ret; - } -- priv = pgpio->priv; - - /* disable, and ack any pending gpio interrupts */ - nv_wr32(dev, 0xe050, 0x00000000); -@@ -293,7 +296,7 @@ nv50_gpio_isr(struct drm_device *dev) - continue; - gpioh->inhibit = true; - -- queue_work(dev_priv->wq, &gpioh->work); -+ schedule_work(&gpioh->work); - } - spin_unlock(&priv->lock); - } -diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c -index 37e21d2..7950bac 100644 ---- a/drivers/gpu/drm/nouveau/nv50_graph.c -+++ b/drivers/gpu/drm/nouveau/nv50_graph.c -@@ -95,13 +95,41 @@ nv50_graph_init_regs__nv(struct drm_device *dev) - } - - static void --nv50_graph_init_regs(struct drm_device *dev) -+nv50_graph_init_zcull(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int i; -+ - NV_DEBUG(dev, "\n"); - -- nv_wr32(dev, NV04_PGRAPH_DEBUG_3, -- (1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */); -- nv_wr32(dev, 0x402ca8, 0x800); -+ switch (dev_priv->chipset & 0xf0) { -+ case 0x50: -+ case 0x80: -+ case 0x90: -+ nv_wr32(dev, 0x402ca8, 0x00000800); -+ break; -+ case 0xa0: -+ default: -+ nv_wr32(dev, 0x402cc0, 0x00000000); -+ if (dev_priv->chipset == 0xa0 || -+ dev_priv->chipset == 0xaa || -+ dev_priv->chipset == 0xac) { -+ nv_wr32(dev, 0x402ca8, 0x00000802); -+ } else { -+ nv_wr32(dev, 0x402cc0, 0x00000000); -+ nv_wr32(dev, 0x402ca8, 0x00000002); -+ } -+ -+ break; -+ } -+ -+ /* zero out zcull regions */ -+ for (i = 0; i < 8; i++) { -+ nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000); -+ nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000); -+ nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000); -+ nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000); -+ } - } - - static int -@@ -136,6 +164,7 @@ nv50_graph_init_ctxctl(struct drm_device *dev) - } - kfree(cp); - -+ nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ - nv_wr32(dev, 0x400320, 4); - nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); - nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0); -@@ -151,7 +180,7 @@ nv50_graph_init(struct drm_device *dev) - - nv50_graph_init_reset(dev); - nv50_graph_init_regs__nv(dev); -- nv50_graph_init_regs(dev); -+ nv50_graph_init_zcull(dev); - - ret = nv50_graph_init_ctxctl(dev); - if (ret) -@@ -409,12 +438,7 @@ static int - nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) - { -- struct nouveau_page_flip_state s; -- -- if (!nouveau_finish_page_flip(chan, &s)) { -- /* XXX - Do something here */ -- } -- -+ nouveau_finish_page_flip(chan, NULL); - return 0; - } - -@@ -479,7 +503,7 @@ nv50_graph_tlb_flush(struct drm_device *dev) - } - - void --nv86_graph_tlb_flush(struct drm_device *dev) -+nv84_graph_tlb_flush(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -@@ -524,13 +548,12 @@ nv86_graph_tlb_flush(struct drm_device *dev) - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - } - --static struct nouveau_enum nv50_mp_exec_error_names[] = --{ -- { 3, "STACK_UNDERFLOW" }, -- { 4, "QUADON_ACTIVE" }, -- { 8, "TIMEOUT" }, -- { 0x10, "INVALID_OPCODE" }, -- { 0x40, "BREAKPOINT" }, -+static struct nouveau_enum nv50_mp_exec_error_names[] = { -+ { 3, "STACK_UNDERFLOW", NULL }, -+ { 4, "QUADON_ACTIVE", NULL }, -+ { 8, "TIMEOUT", NULL }, -+ { 0x10, "INVALID_OPCODE", NULL }, -+ { 0x40, "BREAKPOINT", NULL }, - {} - }; - -@@ -558,47 +581,47 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = { - - /* There must be a *lot* of these. Will take some time to gather them up. */ - struct nouveau_enum nv50_data_error_names[] = { -- { 0x00000003, "INVALID_QUERY_OR_TEXTURE" }, -- { 0x00000004, "INVALID_VALUE" }, -- { 0x00000005, "INVALID_ENUM" }, -- { 0x00000008, "INVALID_OBJECT" }, -- { 0x00000009, "READ_ONLY_OBJECT" }, -- { 0x0000000a, "SUPERVISOR_OBJECT" }, -- { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" }, -- { 0x0000000c, "INVALID_BITFIELD" }, -- { 0x0000000d, "BEGIN_END_ACTIVE" }, -- { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" }, -- { 0x0000000f, "VIEWPORT_ID_NEEDS_GP" }, -- { 0x00000010, "RT_DOUBLE_BIND" }, -- { 0x00000011, "RT_TYPES_MISMATCH" }, -- { 0x00000012, "RT_LINEAR_WITH_ZETA" }, -- { 0x00000015, "FP_TOO_FEW_REGS" }, -- { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" }, -- { 0x00000017, "RT_LINEAR_WITH_MSAA" }, -- { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" }, -- { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" }, -- { 0x0000001a, "RT_INVALID_ALIGNMENT" }, -- { 0x0000001b, "SAMPLER_OVER_LIMIT" }, -- { 0x0000001c, "TEXTURE_OVER_LIMIT" }, -- { 0x0000001e, "GP_TOO_MANY_OUTPUTS" }, -- { 0x0000001f, "RT_BPP128_WITH_MS8" }, -- { 0x00000021, "Z_OUT_OF_BOUNDS" }, -- { 0x00000023, "XY_OUT_OF_BOUNDS" }, -- { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" }, -- { 0x00000028, "CP_NO_REG_SPACE_STRIPED" }, -- { 0x00000029, "CP_NO_REG_SPACE_PACKED" }, -- { 0x0000002a, "CP_NOT_ENOUGH_WARPS" }, -- { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" }, -- { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" }, -- { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" }, -- { 0x0000002e, "CP_NO_BLOCKDIM_LATCH" }, -- { 0x00000031, "ENG2D_FORMAT_MISMATCH" }, -- { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" }, -- { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" }, -- { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" }, -- { 0x00000046, "LAYER_ID_NEEDS_GP" }, -- { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" }, -- { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" }, -+ { 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL }, -+ { 0x00000004, "INVALID_VALUE", NULL }, -+ { 0x00000005, "INVALID_ENUM", NULL }, -+ { 0x00000008, "INVALID_OBJECT", NULL }, -+ { 0x00000009, "READ_ONLY_OBJECT", NULL }, -+ { 0x0000000a, "SUPERVISOR_OBJECT", NULL }, -+ { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL }, -+ { 0x0000000c, "INVALID_BITFIELD", NULL }, -+ { 0x0000000d, "BEGIN_END_ACTIVE", NULL }, -+ { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL }, -+ { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL }, -+ { 0x00000010, "RT_DOUBLE_BIND", NULL }, -+ { 0x00000011, "RT_TYPES_MISMATCH", NULL }, -+ { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL }, -+ { 0x00000015, "FP_TOO_FEW_REGS", NULL }, -+ { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL }, -+ { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL }, -+ { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL }, -+ { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL }, -+ { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL }, -+ { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL }, -+ { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL }, -+ { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL }, -+ { 0x0000001f, "RT_BPP128_WITH_MS8", NULL }, -+ { 0x00000021, "Z_OUT_OF_BOUNDS", NULL }, -+ { 0x00000023, "XY_OUT_OF_BOUNDS", NULL }, -+ { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL }, -+ { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL }, -+ { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL }, -+ { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL }, -+ { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL }, -+ { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL }, -+ { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL }, -+ { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL }, -+ { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL }, -+ { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL }, -+ { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL }, -+ { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL }, -+ { 0x00000046, "LAYER_ID_NEEDS_GP", NULL }, -+ { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL }, -+ { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL }, - {} - }; - -@@ -639,7 +662,7 @@ nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) - nv_rd32(dev, addr + 0x20); - pc = nv_rd32(dev, addr + 0x24); - oplow = nv_rd32(dev, addr + 0x70); -- ophigh= nv_rd32(dev, addr + 0x74); -+ ophigh = nv_rd32(dev, addr + 0x74); - NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " - "TP %d MP %d: ", tpid, i); - nouveau_enum_print(nv50_mp_exec_error_names, status); -@@ -678,7 +701,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, - tps++; - switch (type) { - case 6: /* texture error... unknown for now */ -- nv50_fb_vm_trap(dev, display, name); - if (display) { - NV_ERROR(dev, "magic set %d:\n", i); - for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) -@@ -701,7 +723,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, - uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); - uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); - uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); -- nv50_fb_vm_trap(dev, display, name); - /* 2d engine destination */ - if (ustatus & 0x00000010) { - if (display) { -@@ -912,10 +933,10 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid - printk("\n"); - NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" - " %08x %08x %08x\n", -- nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804), -- nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c), -- nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814), -- nv_rd32(dev, 0x40581c)); -+ nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004), -+ nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c), -+ nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014), -+ nv_rd32(dev, 0x40501c)); - - } - -@@ -1044,6 +1065,7 @@ nv50_graph_isr(struct drm_device *dev) - NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " - "class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, subc, class, mthd, data); -+ nv50_fb_vm_trap(dev, 1); - } - } - -diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c -index 336aab2..de9abff 100644 ---- a/drivers/gpu/drm/nouveau/nv50_grctx.c -+++ b/drivers/gpu/drm/nouveau/nv50_grctx.c -@@ -747,7 +747,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) - gr_def(ctx, offset + 0x64, 0x0000001f); - gr_def(ctx, offset + 0x68, 0x0000000f); - gr_def(ctx, offset + 0x6c, 0x0000000f); -- } else if(dev_priv->chipset < 0xa0) { -+ } else if (dev_priv->chipset < 0xa0) { - cp_ctx(ctx, offset + 0x50, 1); - cp_ctx(ctx, offset + 0x70, 1); - } else { -@@ -924,7 +924,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) - dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */ - } else { - dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */ -- } -+ } - dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */ - if (dev_priv->chipset != 0x50) - dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */ -@@ -1803,9 +1803,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) - xf_emit(ctx, 1, 0); /* 1ff */ - xf_emit(ctx, 8, 0); /* 0? */ - xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ -- } -- else -- { -+ } else { - xf_emit(ctx, 0xc, 0); /* RO */ - /* SEEK */ - xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ -@@ -2836,7 +2834,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) - xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ - if (IS_NVA3F(dev_priv->chipset)) - xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ -- if(dev_priv->chipset == 0x50) -+ if (dev_priv->chipset == 0x50) - xf_emit(ctx, 1, 0); /* ff */ - else - xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ -diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c -index e57caa2..993ad3f 100644 ---- a/drivers/gpu/drm/nouveau/nv50_instmem.c -+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c -@@ -300,7 +300,7 @@ nv50_instmem_resume(struct drm_device *dev) - } - - struct nv50_gpuobj_node { -- struct nouveau_vram *vram; -+ struct nouveau_mem *vram; - struct nouveau_vma chan_vma; - u32 align; - }; -@@ -404,23 +404,25 @@ void - nv50_instmem_flush(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x00330c, 0x00000001); - if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } - - void - nv84_instmem_flush(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x070000, 0x00000001); - if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000)) - NV_ERROR(dev, "PRAMIN flush timeout\n"); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } - -diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c -index b4a5ecb..c25c593 100644 ---- a/drivers/gpu/drm/nouveau/nv50_sor.c -+++ b/drivers/gpu/drm/nouveau/nv50_sor.c -@@ -41,8 +41,7 @@ nv50_sor_disconnect(struct drm_encoder *encoder) - { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(dev)->master; - int ret; - - if (!nv_encoder->crtc) -@@ -184,8 +183,7 @@ static void - nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - { -- struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; -- struct nouveau_channel *evo = dev_priv->evo; -+ struct nouveau_channel *evo = nv50_display(encoder->dev)->master; - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; - struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); -diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c -index 6144156..6c26944 100644 ---- a/drivers/gpu/drm/nouveau/nv50_vm.c -+++ b/drivers/gpu/drm/nouveau/nv50_vm.c -@@ -31,7 +31,6 @@ void - nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - struct nouveau_gpuobj *pgt[2]) - { -- struct drm_nouveau_private *dev_priv = pgd->dev->dev_private; - u64 phys = 0xdeadcafe00000000ULL; - u32 coverage = 0; - -@@ -58,10 +57,9 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, - } - - static inline u64 --nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -- u64 phys, u32 memtype, u32 target) -+nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) - { -- struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; -+ struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private; - - phys |= 1; /* present */ - phys |= (u64)memtype << 40; -@@ -85,12 +83,13 @@ nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, - - void - nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -- struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) -+ struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) - { -+ u32 comp = (mem->memtype & 0x180) >> 7; - u32 block; - int i; - -- phys = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0); -+ phys = nv50_vm_addr(vma, phys, mem->memtype, 0); - pte <<= 3; - cnt <<= 3; - -@@ -107,6 +106,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, - - phys += block << (vma->node->type - 3); - cnt -= block; -+ if (comp) { -+ u32 tag = mem->tag->start + ((delta >> 16) * comp); -+ offset_h |= (tag << 17); -+ delta += block << (vma->node->type - 3); -+ } - - while (block) { - nv_wo32(pgt, pte + 0, offset_l); -@@ -119,11 +123,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, - - void - nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -- u32 pte, dma_addr_t *list, u32 cnt) -+ struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) - { - pte <<= 3; - while (cnt--) { -- u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2); -+ u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2); - nv_wo32(pgt, pte + 0, lower_32_bits(phys)); - nv_wo32(pgt, pte + 4, upper_32_bits(phys)); - pte += 8; -@@ -170,10 +174,11 @@ void - nv50_vm_flush_engine(struct drm_device *dev, int engine) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ unsigned long flags; - -- spin_lock(&dev_priv->ramin_lock); -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - nv_wr32(dev, 0x100c80, (engine << 16) | 1); - if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) - NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); -- spin_unlock(&dev_priv->ramin_lock); -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } -diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c -index 58e98ad..ffbc3d8 100644 ---- a/drivers/gpu/drm/nouveau/nv50_vram.c -+++ b/drivers/gpu/drm/nouveau/nv50_vram.c -@@ -48,42 +48,49 @@ nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) - } - - void --nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram) -+nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; - struct nouveau_mm *mm = man->priv; - struct nouveau_mm_node *this; -- struct nouveau_vram *vram; -+ struct nouveau_mem *mem; - -- vram = *pvram; -- *pvram = NULL; -- if (unlikely(vram == NULL)) -+ mem = *pmem; -+ *pmem = NULL; -+ if (unlikely(mem == NULL)) - return; - - mutex_lock(&mm->mutex); -- while (!list_empty(&vram->regions)) { -- this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); -+ while (!list_empty(&mem->regions)) { -+ this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); - - list_del(&this->rl_entry); - nouveau_mm_put(mm, this); - } -+ -+ if (mem->tag) { -+ drm_mm_put_block(mem->tag); -+ mem->tag = NULL; -+ } - mutex_unlock(&mm->mutex); - -- kfree(vram); -+ kfree(mem); - } - - int - nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, -- u32 type, struct nouveau_vram **pvram) -+ u32 memtype, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; - struct nouveau_mm *mm = man->priv; - struct nouveau_mm_node *r; -- struct nouveau_vram *vram; -+ struct nouveau_mem *mem; -+ int comp = (memtype & 0x300) >> 8; -+ int type = (memtype & 0x07f); - int ret; - - if (!types[type]) -@@ -92,32 +99,46 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, - align >>= 12; - size_nc >>= 12; - -- vram = kzalloc(sizeof(*vram), GFP_KERNEL); -- if (!vram) -+ mem = kzalloc(sizeof(*mem), GFP_KERNEL); -+ if (!mem) - return -ENOMEM; - -- INIT_LIST_HEAD(&vram->regions); -- vram->dev = dev_priv->dev; -- vram->memtype = type; -- vram->size = size; -- - mutex_lock(&mm->mutex); -+ if (comp) { -+ if (align == 16) { -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ int n = (size >> 4) * comp; -+ -+ mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0); -+ if (mem->tag) -+ mem->tag = drm_mm_get_block(mem->tag, n, 0); -+ } -+ -+ if (unlikely(!mem->tag)) -+ comp = 0; -+ } -+ -+ INIT_LIST_HEAD(&mem->regions); -+ mem->dev = dev_priv->dev; -+ mem->memtype = (comp << 7) | type; -+ mem->size = size; -+ - do { - ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); - if (ret) { - mutex_unlock(&mm->mutex); -- nv50_vram_del(dev, &vram); -+ nv50_vram_del(dev, &mem); - return ret; - } - -- list_add_tail(&r->rl_entry, &vram->regions); -+ list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - -- r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); -- vram->offset = (u64)r->offset << 12; -- *pvram = vram; -+ r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); -+ mem->offset = (u64)r->offset << 12; -+ *pmem = mem; - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c -index ec18ae1..fabc7fd 100644 ---- a/drivers/gpu/drm/nouveau/nv84_crypt.c -+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c -@@ -136,5 +136,5 @@ nv84_crypt_isr(struct drm_device *dev) - nv_wr32(dev, 0x102130, stat); - nv_wr32(dev, 0x10200c, 0x10); - -- nv50_fb_vm_trap(dev, show, "PCRYPT"); -+ nv50_fb_vm_trap(dev, show); - } -diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c -index dbbafed..e4b2b9e 100644 ---- a/drivers/gpu/drm/nouveau/nva3_pm.c -+++ b/drivers/gpu/drm/nouveau/nva3_pm.c -@@ -27,32 +27,74 @@ - #include "nouveau_bios.h" - #include "nouveau_pm.h" - --/*XXX: boards using limits 0x40 need fixing, the register layout -- * is correct here, but, there's some other funny magic -- * that modifies things, so it's not likely we'll set/read -- * the correct timings yet.. working on it... -+/* This is actually a lot more complex than it appears here, but hopefully -+ * this should be able to deal with what the VBIOS leaves for us.. -+ * -+ * If not, well, I'll jump off that bridge when I come to it. - */ - - struct nva3_pm_state { -- struct pll_lims pll; -- int N, M, P; -+ enum pll_types type; -+ u32 src0; -+ u32 src1; -+ u32 ctrl; -+ u32 coef; -+ u32 old_pnm; -+ u32 new_pnm; -+ u32 new_div; - }; - -+static int -+nva3_pm_pll_offset(u32 id) -+{ -+ static const u32 pll_map[] = { -+ 0x00, PLL_CORE, -+ 0x01, PLL_SHADER, -+ 0x02, PLL_MEMORY, -+ 0x00, 0x00 -+ }; -+ const u32 *map = pll_map; -+ -+ while (map[1]) { -+ if (id == map[1]) -+ return map[0]; -+ map += 2; -+ } -+ -+ return -ENOENT; -+} -+ - int - nva3_pm_clock_get(struct drm_device *dev, u32 id) - { -+ u32 src0, src1, ctrl, coef; - struct pll_lims pll; -- int P, N, M, ret; -- u32 reg; -+ int ret, off; -+ int P, N, M; - - ret = get_pll_limits(dev, id, &pll); - if (ret) - return ret; - -- reg = nv_rd32(dev, pll.reg + 4); -- P = (reg & 0x003f0000) >> 16; -- N = (reg & 0x0000ff00) >> 8; -- M = (reg & 0x000000ff); -+ off = nva3_pm_pll_offset(id); -+ if (off < 0) -+ return off; -+ -+ src0 = nv_rd32(dev, 0x4120 + (off * 4)); -+ src1 = nv_rd32(dev, 0x4160 + (off * 4)); -+ ctrl = nv_rd32(dev, pll.reg + 0); -+ coef = nv_rd32(dev, pll.reg + 4); -+ NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ id, src0, src1, ctrl, coef); -+ -+ if (ctrl & 0x00000008) { -+ u32 div = ((src1 & 0x003c0000) >> 18) + 1; -+ return (pll.refclk * 2) / div; -+ } -+ -+ P = (coef & 0x003f0000) >> 16; -+ N = (coef & 0x0000ff00) >> 8; -+ M = (coef & 0x000000ff); - return pll.refclk * N / M / P; - } - -@@ -60,36 +102,103 @@ void * - nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, - u32 id, int khz) - { -- struct nva3_pm_state *state; -- int dummy, ret; -+ struct nva3_pm_state *pll; -+ struct pll_lims limits; -+ int N, M, P, diff; -+ int ret, off; -+ -+ ret = get_pll_limits(dev, id, &limits); -+ if (ret < 0) -+ return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ -+ off = nva3_pm_pll_offset(id); -+ if (id < 0) -+ return ERR_PTR(-EINVAL); - -- state = kzalloc(sizeof(*state), GFP_KERNEL); -- if (!state) -+ -+ pll = kzalloc(sizeof(*pll), GFP_KERNEL); -+ if (!pll) - return ERR_PTR(-ENOMEM); -+ pll->type = id; -+ pll->src0 = 0x004120 + (off * 4); -+ pll->src1 = 0x004160 + (off * 4); -+ pll->ctrl = limits.reg + 0; -+ pll->coef = limits.reg + 4; - -- ret = get_pll_limits(dev, id, &state->pll); -- if (ret < 0) { -- kfree(state); -- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ /* If target clock is within [-2, 3) MHz of a divisor, we'll -+ * use that instead of calculating MNP values -+ */ -+ pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16); -+ if (pll->new_div) { -+ diff = khz - ((limits.refclk * 2) / pll->new_div); -+ if (diff < -2000 || diff >= 3000) -+ pll->new_div = 0; - } - -- ret = nv50_calc_pll2(dev, &state->pll, khz, &state->N, &dummy, -- &state->M, &state->P); -- if (ret < 0) { -- kfree(state); -- return ERR_PTR(ret); -+ if (!pll->new_div) { -+ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); -+ if (ret < 0) -+ return ERR_PTR(ret); -+ -+ pll->new_pnm = (P << 16) | (N << 8) | M; -+ pll->new_div = 2 - 1; -+ } else { -+ pll->new_pnm = 0; -+ pll->new_div--; - } - -- return state; -+ if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101) -+ pll->old_pnm = nv_rd32(dev, pll->coef); -+ return pll; - } - - void - nva3_pm_clock_set(struct drm_device *dev, void *pre_state) - { -- struct nva3_pm_state *state = pre_state; -- u32 reg = state->pll.reg; -+ struct nva3_pm_state *pll = pre_state; -+ u32 ctrl = 0; -+ -+ /* For the memory clock, NVIDIA will build a "script" describing -+ * the reclocking process and ask PDAEMON to execute it. -+ */ -+ if (pll->type == PLL_MEMORY) { -+ nv_wr32(dev, 0x100210, 0); -+ nv_wr32(dev, 0x1002dc, 1); -+ nv_wr32(dev, 0x004018, 0x00001000); -+ ctrl = 0x18000100; -+ } -+ -+ if (pll->old_pnm || !pll->new_pnm) { -+ nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 | -+ (pll->new_div << 18)); -+ nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); -+ nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); -+ } -+ -+ if (pll->new_pnm) { -+ nv_mask(dev, pll->src0, 0x00000101, 0x00000101); -+ nv_wr32(dev, pll->coef, pll->new_pnm); -+ nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); -+ nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000); -+ nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010); -+ nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl); -+ nv_mask(dev, pll->src1, 0x00000100, 0x00000000); -+ nv_mask(dev, pll->src1, 0x00000001, 0x00000000); -+ if (pll->type == PLL_MEMORY) -+ nv_wr32(dev, 0x4018, 0x10005000); -+ } else { -+ nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); -+ nv_mask(dev, pll->src0, 0x00000100, 0x00000000); -+ nv_mask(dev, pll->src0, 0x00000001, 0x00000000); -+ if (pll->type == PLL_MEMORY) -+ nv_wr32(dev, 0x4018, 0x1000d000); -+ } -+ -+ if (pll->type == PLL_MEMORY) { -+ nv_wr32(dev, 0x1002dc, 0); -+ nv_wr32(dev, 0x100210, 0x80000000); -+ } - -- nv_wr32(dev, reg + 4, (state->P << 16) | (state->N << 8) | state->M); -- kfree(state); -+ kfree(pll); - } - -diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c -index 26a9960..08e6b11 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_fb.c -+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c -@@ -1,5 +1,5 @@ - /* -- * Copyright 2010 Red Hat Inc. -+ * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), -@@ -23,16 +23,80 @@ - */ - - #include "drmP.h" -- -+#include "drm.h" - #include "nouveau_drv.h" -+#include "nouveau_drm.h" -+ -+struct nvc0_fb_priv { -+ struct page *r100c10_page; -+ dma_addr_t r100c10; -+}; -+ -+static void -+nvc0_fb_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ struct nvc0_fb_priv *priv = pfb->priv; -+ -+ if (priv->r100c10_page) { -+ pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, -+ PCI_DMA_BIDIRECTIONAL); -+ __free_page(priv->r100c10_page); -+ } -+ -+ kfree(priv); -+ pfb->priv = NULL; -+} -+ -+static int -+nvc0_fb_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ struct nvc0_fb_priv *priv; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ pfb->priv = priv; -+ -+ priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); -+ if (!priv->r100c10_page) { -+ nvc0_fb_destroy(dev); -+ return -ENOMEM; -+ } -+ -+ priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, -+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { -+ nvc0_fb_destroy(dev); -+ return -EFAULT; -+ } -+ -+ return 0; -+} - - int - nvc0_fb_init(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_fb_priv *priv; -+ int ret; -+ -+ if (!dev_priv->engine.fb.priv) { -+ ret = nvc0_fb_create(dev); -+ if (ret) -+ return ret; -+ } -+ priv = dev_priv->engine.fb.priv; -+ -+ nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); - return 0; - } - - void - nvc0_fb_takedown(struct drm_device *dev) - { -+ nvc0_fb_destroy(dev); - } -diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c -index e6f92c5..55a4245 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_fifo.c -+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c -@@ -116,7 +116,7 @@ nvc0_fifo_create_context(struct nouveau_channel *chan) - - /* allocate vram for control regs, map into polling area */ - ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, -- 0, 0, true, true, &fifoch->user); -+ 0, 0, &fifoch->user); - if (ret) - goto error; - -@@ -355,19 +355,57 @@ nvc0_fifo_init(struct drm_device *dev) - } - - struct nouveau_enum nvc0_fifo_fault_unit[] = { -- { 0, "PGRAPH" }, -- { 3, "PEEPHOLE" }, -- { 4, "BAR1" }, -- { 5, "BAR3" }, -- { 7, "PFIFO" }, -+ { 0x00, "PGRAPH" }, -+ { 0x03, "PEEPHOLE" }, -+ { 0x04, "BAR1" }, -+ { 0x05, "BAR3" }, -+ { 0x07, "PFIFO" }, -+ { 0x10, "PBSP" }, -+ { 0x11, "PPPP" }, -+ { 0x13, "PCOUNTER" }, -+ { 0x14, "PVP" }, -+ { 0x15, "PCOPY0" }, -+ { 0x16, "PCOPY1" }, -+ { 0x17, "PDAEMON" }, - {} - }; - - struct nouveau_enum nvc0_fifo_fault_reason[] = { -- { 0, "PT_NOT_PRESENT" }, -- { 1, "PT_TOO_SHORT" }, -- { 2, "PAGE_NOT_PRESENT" }, -- { 3, "VM_LIMIT_EXCEEDED" }, -+ { 0x00, "PT_NOT_PRESENT" }, -+ { 0x01, "PT_TOO_SHORT" }, -+ { 0x02, "PAGE_NOT_PRESENT" }, -+ { 0x03, "VM_LIMIT_EXCEEDED" }, -+ { 0x04, "NO_CHANNEL" }, -+ { 0x05, "PAGE_SYSTEM_ONLY" }, -+ { 0x06, "PAGE_READ_ONLY" }, -+ { 0x0a, "COMPRESSED_SYSRAM" }, -+ { 0x0c, "INVALID_STORAGE_TYPE" }, -+ {} -+}; -+ -+struct nouveau_enum nvc0_fifo_fault_hubclient[] = { -+ { 0x01, "PCOPY0" }, -+ { 0x02, "PCOPY1" }, -+ { 0x04, "DISPATCH" }, -+ { 0x05, "CTXCTL" }, -+ { 0x06, "PFIFO" }, -+ { 0x07, "BAR_READ" }, -+ { 0x08, "BAR_WRITE" }, -+ { 0x0b, "PVP" }, -+ { 0x0c, "PPPP" }, -+ { 0x0d, "PBSP" }, -+ { 0x11, "PCOUNTER" }, -+ { 0x12, "PDAEMON" }, -+ { 0x14, "CCACHE" }, -+ { 0x15, "CCACHE_POST" }, -+ {} -+}; -+ -+struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { -+ { 0x01, "TEX" }, -+ { 0x0c, "ESETUP" }, -+ { 0x0e, "CTXCTL" }, -+ { 0x0f, "PROP" }, - {} - }; - -@@ -385,12 +423,20 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit) - u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); - u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); - u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); -+ u32 client = (stat & 0x00001f00) >> 8; - - NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", - (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); - nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); - printk("] from "); - nouveau_enum_print(nvc0_fifo_fault_unit, unit); -+ if (stat & 0x00000040) { -+ printk("/"); -+ nouveau_enum_print(nvc0_fifo_fault_hubclient, client); -+ } else { -+ printk("/GPC%d/", (stat & 0x1f000000) >> 24); -+ nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); -+ } - printk(" on channel 0x%010llx\n", (u64)inst << 12); - } - -@@ -418,6 +464,12 @@ nvc0_fifo_isr(struct drm_device *dev) - { - u32 stat = nv_rd32(dev, 0x002100); - -+ if (stat & 0x00000100) { -+ NV_INFO(dev, "PFIFO: unknown status 0x00000100\n"); -+ nv_wr32(dev, 0x002100, 0x00000100); -+ stat &= ~0x00000100; -+ } -+ - if (stat & 0x10000000) { - u32 units = nv_rd32(dev, 0x00259c); - u32 u = units; -@@ -446,10 +498,15 @@ nvc0_fifo_isr(struct drm_device *dev) - stat &= ~0x20000000; - } - -+ if (stat & 0x40000000) { -+ NV_INFO(dev, "PFIFO: unknown status 0x40000000\n"); -+ nv_mask(dev, 0x002a00, 0x00000000, 0x00000000); -+ stat &= ~0x40000000; -+ } -+ - if (stat) { - NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat); - nv_wr32(dev, 0x002100, stat); -+ nv_wr32(dev, 0x002140, 0); - } -- -- nv_wr32(dev, 0x2140, 0); - } -diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c -index eb18a7e..68f5c3f 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_graph.c -+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c -@@ -200,15 +200,15 @@ nvc0_graph_create_context(struct nouveau_channel *chan) - for (i = 0; i < priv->grctx_size; i += 4) - nv_wo32(grctx, i, priv->grctx_vals[i / 4]); - -- nv_wo32(grctx, 0xf4, 0); -- nv_wo32(grctx, 0xf8, 0); -- nv_wo32(grctx, 0x10, grch->mmio_nr); -- nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst)); -- nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst)); -- nv_wo32(grctx, 0x1c, 1); -- nv_wo32(grctx, 0x20, 0); -- nv_wo32(grctx, 0x28, 0); -- nv_wo32(grctx, 0x2c, 0); -+ nv_wo32(grctx, 0xf4, 0); -+ nv_wo32(grctx, 0xf8, 0); -+ nv_wo32(grctx, 0x10, grch->mmio_nr); -+ nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst)); -+ nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst)); -+ nv_wo32(grctx, 0x1c, 1); -+ nv_wo32(grctx, 0x20, 0); -+ nv_wo32(grctx, 0x28, 0); -+ nv_wo32(grctx, 0x2c, 0); - pinstmem->flush(dev); - return 0; - -@@ -299,6 +299,14 @@ nvc0_graph_takedown(struct drm_device *dev) - } - - static int -+nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, -+ u32 class, u32 mthd, u32 data) -+{ -+ nouveau_finish_page_flip(chan, NULL); -+ return 0; -+} -+ -+static int - nvc0_graph_create(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -395,6 +403,7 @@ nvc0_graph_create(struct drm_device *dev) - nouveau_irq_register(dev, 25, nvc0_runk140_isr); - NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ - NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ -+ NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); - NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ - NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ - return 0; -@@ -443,28 +452,30 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; - int gpc; -- -- // TP ROP UNKVAL(magic_not_rop_nr) -- // 450: 4/0/0/0 2 3 -- // 460: 3/4/0/0 4 1 -- // 465: 3/4/4/0 4 7 -- // 470: 3/3/4/4 5 5 -- // 480: 3/4/4/4 6 6 -- -- // magicgpc918 -- // 450: 00200000 00000000001000000000000000000000 -- // 460: 00124925 00000000000100100100100100100101 -- // 465: 000ba2e9 00000000000010111010001011101001 -- // 470: 00092493 00000000000010010010010010010011 -- // 480: 00088889 00000000000010001000100010001001 -- -- /* filled values up to tp_total, remainder 0 */ -- // 450: 00003210 00000000 00000000 00000000 -- // 460: 02321100 00000000 00000000 00000000 -- // 465: 22111000 00000233 00000000 00000000 -- // 470: 11110000 00233222 00000000 00000000 -- // 480: 11110000 03332222 00000000 00000000 -- -+ -+ /* -+ * TP ROP UNKVAL(magic_not_rop_nr) -+ * 450: 4/0/0/0 2 3 -+ * 460: 3/4/0/0 4 1 -+ * 465: 3/4/4/0 4 7 -+ * 470: 3/3/4/4 5 5 -+ * 480: 3/4/4/4 6 6 -+ -+ * magicgpc918 -+ * 450: 00200000 00000000001000000000000000000000 -+ * 460: 00124925 00000000000100100100100100100101 -+ * 465: 000ba2e9 00000000000010111010001011101001 -+ * 470: 00092493 00000000000010010010010010010011 -+ * 480: 00088889 00000000000010001000100010001001 -+ -+ * filled values up to tp_total, remainder 0 -+ * 450: 00003210 00000000 00000000 00000000 -+ * 460: 02321100 00000000 00000000 00000000 -+ * 465: 22111000 00000233 00000000 00000000 -+ * 470: 11110000 00233222 00000000 00000000 -+ * 480: 11110000 03332222 00000000 00000000 -+ */ -+ - nv_wr32(dev, GPC_BCAST(0x0980), priv->magicgpc980[0]); - nv_wr32(dev, GPC_BCAST(0x0984), priv->magicgpc980[1]); - nv_wr32(dev, GPC_BCAST(0x0988), priv->magicgpc980[2]); -@@ -640,7 +651,6 @@ nvc0_graph_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; -- struct nvc0_graph_priv *priv; - int ret; - - dev_priv->engine.graph.accel_blocked = true; -@@ -665,13 +675,12 @@ nvc0_graph_init(struct drm_device *dev) - if (ret) - return ret; - } -- priv = pgraph->priv; - - nvc0_graph_init_obj418880(dev); - nvc0_graph_init_regs(dev); -- //nvc0_graph_init_unitplemented_magics(dev); -+ /*nvc0_graph_init_unitplemented_magics(dev);*/ - nvc0_graph_init_gpc_0(dev); -- //nvc0_graph_init_unitplemented_c242(dev); -+ /*nvc0_graph_init_unitplemented_c242(dev);*/ - - nv_wr32(dev, 0x400500, 0x00010001); - nv_wr32(dev, 0x400100, 0xffffffff); -@@ -730,9 +739,12 @@ nvc0_graph_isr(struct drm_device *dev) - u32 class = nv_rd32(dev, 0x404200 + (subc * 4)); - - if (stat & 0x00000010) { -- NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d " -- "class 0x%04x mthd 0x%04x data 0x%08x\n", -- chid, inst, subc, class, mthd, data); -+ if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) { -+ NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] " -+ "subc %d class 0x%04x mthd 0x%04x " -+ "data 0x%08x\n", -+ chid, inst, subc, class, mthd, data); -+ } - nv_wr32(dev, 0x400100, 0x00000010); - stat &= ~0x00000010; - } -diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h -index 40e26f9..d32b385 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_graph.h -+++ b/drivers/gpu/drm/nouveau/nvc0_graph.h -@@ -28,11 +28,11 @@ - #define GPC_MAX 4 - #define TP_MAX 32 - --#define ROP_BCAST(r) (0x408800 + (r)) --#define ROP_UNIT(u,r) (0x410000 + (u) * 0x400 + (r)) --#define GPC_BCAST(r) (0x418000 + (r)) --#define GPC_UNIT(t,r) (0x500000 + (t) * 0x8000 + (r)) --#define TP_UNIT(t,m,r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) -+#define ROP_BCAST(r) (0x408800 + (r)) -+#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r)) -+#define GPC_BCAST(r) (0x418000 + (r)) -+#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r)) -+#define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) - - struct nvc0_graph_priv { - u8 gpc_nr; -@@ -52,9 +52,9 @@ struct nvc0_graph_priv { - - struct nvc0_graph_chan { - struct nouveau_gpuobj *grctx; -- struct nouveau_gpuobj *unk408004; // 0x418810 too -- struct nouveau_gpuobj *unk40800c; // 0x419004 too -- struct nouveau_gpuobj *unk418810; // 0x419848 too -+ struct nouveau_gpuobj *unk408004; /* 0x418810 too */ -+ struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ -+ struct nouveau_gpuobj *unk418810; /* 0x419848 too */ - struct nouveau_gpuobj *mmio; - int mmio_nr; - }; -diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c -index f880ff7..6cede9f 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_grctx.c -+++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c -@@ -1623,7 +1623,7 @@ nvc0_grctx_generate_rop(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -- // ROPC_BROADCAST -+ /* ROPC_BROADCAST */ - nv_wr32(dev, 0x408800, 0x02802a3c); - nv_wr32(dev, 0x408804, 0x00000040); - nv_wr32(dev, 0x408808, 0x0003e00d); -@@ -1647,7 +1647,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) - { - int i; - -- // GPC_BROADCAST -+ /* GPC_BROADCAST */ - nv_wr32(dev, 0x418380, 0x00000016); - nv_wr32(dev, 0x418400, 0x38004e00); - nv_wr32(dev, 0x418404, 0x71e0ffff); -@@ -1728,7 +1728,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - -- // GPC_BROADCAST.TP_BROADCAST -+ /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(dev, 0x419848, 0x00000000); - nv_wr32(dev, 0x419864, 0x0000012a); - nv_wr32(dev, 0x419888, 0x00000000); -@@ -1741,7 +1741,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev) - nv_wr32(dev, 0x419a1c, 0x00000000); - nv_wr32(dev, 0x419a20, 0x00000800); - if (dev_priv->chipset != 0xc0) -- nv_wr32(dev, 0x00419ac4, 0x0007f440); // 0xc3 -+ nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */ - nv_wr32(dev, 0x419b00, 0x0a418820); - nv_wr32(dev, 0x419b04, 0x062080e6); - nv_wr32(dev, 0x419b08, 0x020398a4); -@@ -1912,13 +1912,13 @@ nvc0_grctx_generate(struct nouveau_channel *chan) - for (i = 1; i < 7; i++) - data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); - -- // GPC_BROADCAST -+ /* GPC_BROADCAST */ - nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) | - priv->magic_not_rop_nr); - for (i = 0; i < 6; i++) - nv_wr32(dev, 0x418b08 + (i * 4), data[i]); - -- // GPC_BROADCAST.TP_BROADCAST -+ /* GPC_BROADCAST.TP_BROADCAST */ - nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) | - priv->magic_not_rop_nr | - data2[0]); -@@ -1926,7 +1926,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) - for (i = 0; i < 6; i++) - nv_wr32(dev, 0x419b00 + (i * 4), data[i]); - -- // UNK78xx -+ /* UNK78xx */ - nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) | - priv->magic_not_rop_nr); - for (i = 0; i < 6; i++) -@@ -1944,7 +1944,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) - gpc = -1; - for (i = 0, gpc = -1; i < 32; i++) { - int ltp = i * (priv->tp_total - 1) / 32; -- -+ - do { - gpc = (gpc + 1) % priv->gpc_nr; - } while (!tpnr[gpc]); -diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c -index e4e83c2..a179e6c 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_vm.c -+++ b/drivers/gpu/drm/nouveau/nvc0_vm.c -@@ -59,7 +59,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) - - void - nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -- struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) -+ struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) - { - u32 next = 1 << (vma->node->type - 8); - -@@ -75,11 +75,11 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, - - void - nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, -- u32 pte, dma_addr_t *list, u32 cnt) -+ struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) - { - pte <<= 3; - while (cnt--) { -- u64 phys = nvc0_vm_addr(vma, *list++, 0, 5); -+ u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5); - nv_wo32(pgt, pte + 0, lower_32_bits(phys)); - nv_wo32(pgt, pte + 4, upper_32_bits(phys)); - pte += 8; -@@ -104,20 +104,27 @@ nvc0_vm_flush(struct nouveau_vm *vm) - struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; - struct drm_device *dev = vm->dev; - struct nouveau_vm_pgd *vpgd; -- u32 r100c80, engine; -+ unsigned long flags; -+ u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; - - pinstmem->flush(vm->dev); - -- if (vm == dev_priv->chan_vm) -- engine = 1; -- else -- engine = 5; -- -+ spin_lock_irqsave(&dev_priv->vm_lock, flags); - list_for_each_entry(vpgd, &vm->pgd_list, head) { -- r100c80 = nv_rd32(dev, 0x100c80); -+ /* looks like maybe a "free flush slots" counter, the -+ * faster you write to 0x100cbc to more it decreases -+ */ -+ if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) { -+ NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n", -+ nv_rd32(dev, 0x100c80), engine); -+ } - nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8); - nv_wr32(dev, 0x100cbc, 0x80000000 | engine); -- if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80)) -- NV_ERROR(dev, "vm flush timeout eng %d\n", engine); -+ /* wait for flush to be queued? */ -+ if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) { -+ NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n", -+ nv_rd32(dev, 0x100c80), engine); -+ } - } -+ spin_unlock_irqrestore(&dev_priv->vm_lock, flags); - } -diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c -index 858eda5..67c6ec6 100644 ---- a/drivers/gpu/drm/nouveau/nvc0_vram.c -+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c -@@ -26,64 +26,78 @@ - #include "nouveau_drv.h" - #include "nouveau_mm.h" - -+/* 0 = unsupported -+ * 1 = non-compressed -+ * 3 = compressed -+ */ -+static const u8 types[256] = { -+ 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, -+ 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, -+ 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -+ 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, -+ 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, -+ 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, -+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 -+}; -+ - bool - nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags) - { -- switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { -- case 0x0000: -- case 0xfe00: -- case 0xdb00: -- case 0x1100: -- return true; -- default: -- break; -- } -- -- return false; -+ u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; -+ return likely((types[memtype] == 1)); - } - - int - nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin, -- u32 type, struct nouveau_vram **pvram) -+ u32 type, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; - struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; - struct nouveau_mm *mm = man->priv; - struct nouveau_mm_node *r; -- struct nouveau_vram *vram; -+ struct nouveau_mem *mem; - int ret; - - size >>= 12; - align >>= 12; - ncmin >>= 12; - -- vram = kzalloc(sizeof(*vram), GFP_KERNEL); -- if (!vram) -+ mem = kzalloc(sizeof(*mem), GFP_KERNEL); -+ if (!mem) - return -ENOMEM; - -- INIT_LIST_HEAD(&vram->regions); -- vram->dev = dev_priv->dev; -- vram->memtype = type; -- vram->size = size; -+ INIT_LIST_HEAD(&mem->regions); -+ mem->dev = dev_priv->dev; -+ mem->memtype = (type & 0xff); -+ mem->size = size; - - mutex_lock(&mm->mutex); - do { - ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r); - if (ret) { - mutex_unlock(&mm->mutex); -- nv50_vram_del(dev, &vram); -+ nv50_vram_del(dev, &mem); - return ret; - } - -- list_add_tail(&r->rl_entry, &vram->regions); -+ list_add_tail(&r->rl_entry, &mem->regions); - size -= r->length; - } while (size); - mutex_unlock(&mm->mutex); - -- r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); -- vram->offset = (u64)r->offset << 12; -- *pvram = vram; -+ r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); -+ mem->offset = (u64)r->offset << 12; -+ *pmem = mem; - return 0; - } - -diff --git a/drivers/gpu/drm/nouveau/nvreg.h b/drivers/gpu/drm/nouveau/nvreg.h -index fe0f253..bbfb1a6 100644 ---- a/drivers/gpu/drm/nouveau/nvreg.h -+++ b/drivers/gpu/drm/nouveau/nvreg.h -@@ -277,6 +277,8 @@ - # define NV_CIO_CRE_EBR_VDE_11 2:2 - # define NV_CIO_CRE_EBR_VRS_11 4:4 - # define NV_CIO_CRE_EBR_VBS_11 6:6 -+# define NV_CIO_CRE_42 0x42 -+# define NV_CIO_CRE_42_OFFSET_11 6:6 - # define NV_CIO_CRE_43 0x43 - # define NV_CIO_CRE_44 0x44 /* head control */ - # define NV_CIO_CRE_CSB 0x45 /* colour saturation boost */ diff --git a/drm-radeon-pageflip-oops-fix.patch b/drm-radeon-pageflip-oops-fix.patch deleted file mode 100644 index dd9cab813..000000000 --- a/drm-radeon-pageflip-oops-fix.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 498c555f56a02ec1059bc150cde84411ba0ac010 Mon Sep 17 00:00:00 2001 -From: Dave Airlie -Date: Sun, 29 May 2011 17:48:32 +1000 -Subject: [PATCH] drm/radeon: fix oops in ttm reserve when pageflipping (v2) - -We need to take a reference to this object, pinning doesn't take a reference -so if userspace deletes the object it can disappear even if pinned. - -v2: fix error paths to unreference properly also. - -should fix: -https://bugzilla.kernel.org/show_bug.cgi?id=32402 -and -https://bugzilla.redhat.com/show_bug.cgi?id=680651 - -Signed-off-by: Dave Airlie ---- - drivers/gpu/drm/radeon/radeon_display.c | 13 ++++++++----- - 1 files changed, 8 insertions(+), 5 deletions(-) - -diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c -index ae247ee..292f73f 100644 ---- a/drivers/gpu/drm/radeon/radeon_display.c -+++ b/drivers/gpu/drm/radeon/radeon_display.c -@@ -264,6 +264,8 @@ static void radeon_unpin_work_func(struct work_struct *__work) - radeon_bo_unreserve(work->old_rbo); - } else - DRM_ERROR("failed to reserve buffer after flip\n"); -+ -+ drm_gem_object_unreference_unlocked(work->old_rbo->gobj); - kfree(work); - } - -@@ -371,6 +373,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, - new_radeon_fb = to_radeon_framebuffer(fb); - /* schedule unpin of the old buffer */ - obj = old_radeon_fb->obj; -+ /* take a reference to the old object */ -+ drm_gem_object_reference(obj); - rbo = obj->driver_private; - work->old_rbo = rbo; - INIT_WORK(&work->work, radeon_unpin_work_func); -@@ -378,12 +382,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, - /* We borrow the event spin lock for protecting unpin_work */ - spin_lock_irqsave(&dev->event_lock, flags); - if (radeon_crtc->unpin_work) { -- spin_unlock_irqrestore(&dev->event_lock, flags); -- kfree(work); -- radeon_fence_unref(&fence); -- - DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); -- return -EBUSY; -+ r = -EBUSY; -+ goto unlock_free; - } - radeon_crtc->unpin_work = work; - radeon_crtc->deferred_flip_completion = 0; -@@ -497,6 +498,8 @@ pflip_cleanup1: - pflip_cleanup: - spin_lock_irqsave(&dev->event_lock, flags); - radeon_crtc->unpin_work = NULL; -+unlock_free: -+ drm_gem_object_unreference_unlocked(old_radeon_fb->obj); - spin_unlock_irqrestore(&dev->event_lock, flags); - radeon_fence_unref(&fence); - kfree(work); --- -1.7.4.4 - diff --git a/drm-radeon-update.patch b/drm-radeon-update.patch deleted file mode 100644 index 205141407..000000000 --- a/drm-radeon-update.patch +++ /dev/null @@ -1,4835 +0,0 @@ -commit 6d7f810bacd0fc2cf3966ec5d756a23735cb781e -Author: Alex Deucher -Date: Tue May 3 19:28:02 2011 -0400 - - drm/radeon/kms: fix gart setup on fusion parts (v2) - - Out of the entire GART/VM subsystem, the hw designers changed - the location of 3 regs. - - v2: airlied: add parameter for userspace to work from. - - Signed-off-by: Alex Deucher - Signed-off-by: Jerome Glisse - Cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 00a99cbeca8ffb6d6165f388230ad49786a1a64e -Author: Dave Airlie -Date: Sun May 1 20:16:30 2011 +1000 - - drm/radeon: fix regression on atom cards with hardcoded EDID record. - - Since fafcf94e2b5732d1e13b440291c53115d2b172e9 introduced an edid size, it seems to have broken this path. - - This manifest as oops on T500 Lenovo laptops with dual graphics primarily. - - Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33812 - - cc: stable@kernel.org - Reviewed-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit ea9254cde5e773424d3af177012ab8019a9a1664 -Author: Alex Deucher -Date: Tue Apr 26 13:27:43 2011 -0400 - - drm/radeon/kms: add info query for tile pipes - - needed by mesa for htile setup. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 5ac5da9419c4b51efa17ef222b0ac82d1af63af8 -Author: Alex Deucher -Date: Tue Apr 26 13:10:20 2011 -0400 - - drm/radeon/kms: add missing safe regs for 6xx/7xx - - needed for HiS in mesa. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 7ad87e13c92ac772cc1eced43df0555ec4a71bbc -Author: Cédric Cano -Date: Tue Apr 19 11:07:13 2011 -0400 - - drm/radeon/kms: fix IH writeback on r6xx+ on big endian machines - - agd5f: fix commit message. - - Signed-off-by: Cedric Cano - Reviewed-by: Michel Dänzer - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 10045c9e73dfa9e53fb429c6d5b1a2261da0ad51 -Author: Alex Deucher -Date: Thu Apr 14 19:07:34 2011 -0400 - - drm/radeon/kms: adjust evergreen display watermark setup - - This patch fixes two issues: - - A disabled crtc does not use any lb, so return 0 for - lb size. This makes the display priority calculation - more exact. - - Only use 1/2 and whole lb partitions. Using smaller - partitions can cause underflow to one of the displays - if you have multiple large displays on the same lb. - - Fixes: - https://bugs.freedesktop.org/show_bug.cgi?id=34534 - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit ea7537dfbe693d8a0d9a3f8dc040fea8d74db625 -Author: Alex Deucher -Date: Tue Apr 12 14:49:24 2011 -0400 - - drm/radeon/kms: properly program vddci on evergreen+ - - Change vddci as well as vddc when changing power modes - on evergreen/ni. Also, properly set vddci on boot up - for ni cards. The vbios only sets the limited clocks - and voltages on boot until the mc ucode is loaded. This - should fix stability problems on some btc cards. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit d45b8c22db23566ec99d330afe69ca0eb99877e3 -Author: Alex Deucher -Date: Tue Apr 12 14:49:23 2011 -0400 - - drm/radeon/kms: add voltage type to atom set voltage function - - This is needed for setting voltages other than vddc. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit ced08b02a89170bfcb0a7cff2b89000fce712efa -Author: Alex Deucher -Date: Tue Apr 12 13:40:18 2011 -0400 - - drm/radeon/kms: fix pcie_p callbacks on btc and cayman - - btc and cayman asics use the same callback for - pcie port registers. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 7e2f10779d1b11b9dc086d95dada8f2d441fcb7c -Author: Alex Deucher -Date: Sat Apr 2 09:15:50 2011 -0400 - - drm/radeon/kms: pageflipping cleanup for avivo+ - - Avoid touching the flip setup regs while - acceleration is running. Set them at modeset - rather than during pageflip. Touching these - regs while acceleration is active caused hangs - on pre-avivo chips. These chips do not seem - to be affected, but better safe than sorry, - plus it avoids repeatedly reprogramming the - regs every flip. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit c079101fc0747d6924edf6b476793267c8707731 -Author: Alex Deucher -Date: Sat Apr 2 09:09:08 2011 -0400 - - drm/radeon/kms: Add support for tv-out dongle on G5 9600 - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 80b359eb082c7e84c9ee970a98578dd409211f52 -Author: Alex Deucher -Date: Wed Mar 2 10:21:05 2011 -0500 - - drm/radeon/kms: allow max clock of 340 Mhz on hdmi 1.3+ - - hdmi 1.3 raises the max clock from 165 Mhz to 340 Mhz. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 4b77fd7824c73fd19a06b3942f498eb23740826d -Author: Alex Deucher -Date: Wed Mar 2 20:07:40 2011 -0500 - - drm/radeon/kms: cayman/evergreen cs checker updates - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 8f62b708e5f4a3e7b617fa7e5ddd9e9becf85920 -Author: Alex Deucher -Date: Wed Mar 2 20:07:39 2011 -0500 - - drm/radeon/kms/cayman: always set certain VGT regs at CP init - - These should be handled by the clear_state setup, but set them - directly as well just to be sure. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 25bfa1ee008f6d8871dd71c529ba25f6492e6b27 -Author: Alex Deucher -Date: Wed Mar 2 20:07:38 2011 -0500 - - drm/radeon/kms: additional default context regs for cayman - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 65a9c7094637d67ffec51dc7373c53f1e4836b79 -Author: Alex Deucher -Date: Wed Mar 2 20:07:37 2011 -0500 - - drm/radeon/kms: add cayman CS check support - - Added to existing evergreen CS checker. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 4655de2aadf3ef4d885600214f8bf989e35087fb -Author: Alex Deucher -Date: Wed Mar 2 20:07:36 2011 -0500 - - drm/radeon/kms: add radeon_asic entry for cayman - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 6110f1c930fa057a0380cbf786350dbd01e9dab9 -Author: Alex Deucher -Date: Wed Mar 2 20:07:35 2011 -0500 - - drm/radeon/kms: add cayman safe regs - - For the CS checker. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit f0c8c61d41e93b1b616b5eb5d29b1bdccb50b6ec -Author: Alex Deucher -Date: Wed Mar 2 20:07:34 2011 -0500 - - drm/radeon/kms/cayman: add asic init/startup/fini/suspend/resume functions - - Cayman is different enough from evergreen to warrant it's own functions. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit f772bd94e036bf8809359b4e37c1aa2ec2dcf4f3 -Author: Alex Deucher -Date: Wed Mar 2 20:07:33 2011 -0500 - - drm/radeon/kms: add cayman asic reset support - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit f83146d1532f80351e8b08ae6063d5792e56914f -Author: Alex Deucher -Date: Wed Mar 2 20:07:32 2011 -0500 - - drm/radeon/kms: add support for cayman irqs - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 004e9f16d1a0dbf2a8787f64b70e8bb3b86abe21 -Author: Alex Deucher -Date: Wed Mar 2 20:07:31 2011 -0500 - - drm/radeon/kms: add support for CP setup on cayman asics - - Cayman asics have 3 ring buffers: - ring 0 supports both gfx and compute - rings 1 and 2 are compute only - - At the moment we only support ring 0. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 5ca642f168996cd6f1dda99ffb17855cc65e493e -Author: Alex Deucher -Date: Wed Mar 2 20:07:30 2011 -0500 - - drm/radeon/kms: add support for cayman gart setup - - This patch sets up the gart in legacy mode. We - probably want to switch to full VM mode at some point. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 8e72474ace85f7a13c88dc360cbfc28dc2fe67e5 -Author: Alex Deucher -Date: Wed Mar 2 20:07:29 2011 -0500 - - drm/radeon/kms: add gpu_init function for cayman - - This may some work to get accel going. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 5b22a85481f452a23dd625e9a389d8f5c0f9b269 -Author: Alex Deucher -Date: Wed Mar 2 20:07:28 2011 -0500 - - drm/radeon/kms: add ucode loader for cayman - - The MC ucode is no longer loaded by the vbios - tables as on previous asics. It now must be loaded - by the driver. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 11fa70b2e7022d25933fc1d17518aeb054752dc9 -Author: Alex Deucher -Date: Wed Mar 2 20:07:27 2011 -0500 - - drm/radeon/kms: add cayman chip family - - Cayman is DCE5 display plus a new 4-way shader block. - 3D state programming is similar to evergreen. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit fe4608d030a121d61dfbc7a80c57706b89fbdabd -Author: Dave Airlie -Date: Tue Mar 1 14:32:27 2011 +1000 - - drm/radeon: add new getparam for number of backends. - - This allows userspace to work out how many DBs there are - for conditional rendering to work. - - Signed-off-by: Dave Airlie - -commit cd3e8f6393bce904aad911b8c261e14d5201d347 -Author: Dave Airlie -Date: Tue Mar 1 12:10:43 2011 +1000 - - drm/radeon: bump version to 2.9 - - This lets r600g enable texture formats and some more extensions. - - Signed-off-by: Dave Airlie - -commit 7855f7a2d8095e04916a097d14cad09c85ebf08a -Author: Dave Airlie -Date: Mon Feb 28 16:11:48 2011 +1000 - - drm/r600: parse the set predication command. (v2) - - This is required for NV_conditional_render and EXT_transform_feedback. - - v2: add evergreen support. - - Signed-off-by: Dave Airlie - -commit 85d824cf58fec0921e4e559cd91dbea50cb7bc20 -Author: Dave Airlie -Date: Mon Feb 28 14:27:03 2011 +1000 - - drm/radeon: make sure ib reads are in-order. - - have to read values from the IB in order as we could cross - a page boundary at any time and won't be able to go backwards. - - Signed-off-by: Dave Airlie - -commit a3f1872b53f046631f48faf19e932f6c9b020446 -Author: Dan Carpenter -Date: Sat Feb 26 04:48:18 2011 +0300 - - drm/radeon/r600_cs: off by one errors - - There are a bunch of off by one errors in the sanity checks here. - - Signed-off-by: Dan Carpenter - Signed-off-by: Dave Airlie - -commit 6c23a39f630acd5c792b731372f5fa227009c7ee -Author: Dave Airlie -Date: Fri Feb 18 05:51:58 2011 +0000 - - drm/radeon: overhaul texture checking. (v3) - - the texture checking code didn't work for block formats like s3tc, - this overhauls it to work for all types. - - v2: add texture array support. - v3: add subsampled formats - - Signed-off-by: Dave Airlie -diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile -index e47eecf..3896ef8 100644 ---- a/drivers/gpu/drm/radeon/Makefile -+++ b/drivers/gpu/drm/radeon/Makefile -@@ -36,6 +36,9 @@ $(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable - $(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable - $(call if_changed,mkregtable) - -+$(obj)/cayman_reg_safe.h: $(src)/reg_srcs/cayman $(obj)/mkregtable -+ $(call if_changed,mkregtable) -+ - $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h - - $(obj)/r200.o: $(obj)/r200_reg_safe.h -@@ -50,7 +53,7 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h - - $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h - --$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h -+$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h $(obj)/cayman_reg_safe.h - - radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \ - radeon_irq.o r300_cmdbuf.o r600_cp.o -@@ -66,7 +69,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ - r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ - r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ - evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ -- radeon_trace_points.o ni.o -+ radeon_trace_points.o ni.o cayman_blit_shaders.o - - radeon-$(CONFIG_COMPAT) += radeon_ioc32.o - radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o -diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c -index bede31c..2bab32f 100644 ---- a/drivers/gpu/drm/radeon/atombios_crtc.c -+++ b/drivers/gpu/drm/radeon/atombios_crtc.c -@@ -1011,6 +1011,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, - uint64_t fb_location; - uint32_t fb_format, fb_pitch_pixels, tiling_flags; - u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); -+ u32 tmp; - int r; - - /* no fb bound */ -@@ -1139,6 +1140,15 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, - WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, - (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); - -+ /* pageflip setup */ -+ /* make sure flip is at vb rather than hb */ -+ tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); -+ tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; -+ WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); -+ -+ /* set pageflip to happen anywhere in vblank interval */ -+ WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); -+ - if (!atomic && fb && fb != crtc->fb) { - radeon_fb = to_radeon_framebuffer(fb); - rbo = radeon_fb->obj->driver_private; -@@ -1169,6 +1179,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, - uint64_t fb_location; - uint32_t fb_format, fb_pitch_pixels, tiling_flags; - u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; -+ u32 tmp; - int r; - - /* no fb bound */ -@@ -1296,6 +1307,15 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, - WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, - (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); - -+ /* pageflip setup */ -+ /* make sure flip is at vb rather than hb */ -+ tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); -+ tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; -+ WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); -+ -+ /* set pageflip to happen anywhere in vblank interval */ -+ WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); -+ - if (!atomic && fb && fb != crtc->fb) { - radeon_fb = to_radeon_framebuffer(fb); - rbo = radeon_fb->obj->driver_private; -diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c -new file mode 100644 -index 0000000..e148ab0 ---- /dev/null -+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c -@@ -0,0 +1,55 @@ -+/* -+ * Copyright 2010 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: -+ * Alex Deucher -+ */ -+ -+#include -+#include -+ -+/* -+ * evergreen cards need to use the 3D engine to blit data which requires -+ * quite a bit of hw state setup. Rather than pull the whole 3D driver -+ * (which normally generates the 3D state) into the DRM, we opt to use -+ * statically generated state tables. The regsiter state and shaders -+ * were hand generated to support blitting functionality. See the 3D -+ * driver or documentation for descriptions of the registers and -+ * shader instructions. -+ */ -+ -+const u32 cayman_default_state[] = -+{ -+ /* XXX fill in additional blit state */ -+ -+ 0xc0026900, -+ 0x00000316, -+ 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ -+ 0x00000010, /* */ -+ -+ 0xc0026900, -+ 0x000000d9, -+ 0x00000000, /* CP_RINGID */ -+ 0x00000000, /* CP_VMID */ -+}; -+ -+const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state); -diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.h b/drivers/gpu/drm/radeon/cayman_blit_shaders.h -new file mode 100644 -index 0000000..33b75e5 ---- /dev/null -+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.h -@@ -0,0 +1,32 @@ -+/* -+ * Copyright 2010 Advanced Micro Devices, Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ * -+ */ -+ -+#ifndef CAYMAN_BLIT_SHADERS_H -+#define CAYMAN_BLIT_SHADERS_H -+ -+extern const u32 cayman_default_state[]; -+ -+extern const u32 cayman_default_size; -+ -+#endif -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index 6140ea1..f7e0376 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -43,17 +43,6 @@ static void evergreen_pcie_gen2_enable(struct radeon_device *rdev); - - void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) - { -- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; -- u32 tmp; -- -- /* make sure flip is at vb rather than hb */ -- tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); -- tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; -- WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); -- -- /* set pageflip to happen anywhere in vblank interval */ -- WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); -- - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); - } -@@ -131,11 +120,16 @@ void evergreen_pm_misc(struct radeon_device *rdev) - struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; - struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; - -- if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { -- if (voltage->voltage != rdev->pm.current_vddc) { -- radeon_atom_set_voltage(rdev, voltage->voltage); -+ if (voltage->type == VOLTAGE_SW) { -+ if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { -+ radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); - rdev->pm.current_vddc = voltage->voltage; -- DRM_DEBUG("Setting: v: %d\n", voltage->voltage); -+ DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); -+ } -+ if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { -+ radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); -+ rdev->pm.current_vddci = voltage->vddci; -+ DRM_DEBUG("Setting: vddci: %d\n", voltage->vddci); - } - } - } -@@ -359,7 +353,7 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, - struct drm_display_mode *mode, - struct drm_display_mode *other_mode) - { -- u32 tmp = 0; -+ u32 tmp; - /* - * Line Buffer Setup - * There are 3 line buffers, each one shared by 2 display controllers. -@@ -369,64 +363,63 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, - * first display controller - * 0 - first half of lb (3840 * 2) - * 1 - first 3/4 of lb (5760 * 2) -- * 2 - whole lb (7680 * 2) -+ * 2 - whole lb (7680 * 2), other crtc must be disabled - * 3 - first 1/4 of lb (1920 * 2) - * second display controller - * 4 - second half of lb (3840 * 2) - * 5 - second 3/4 of lb (5760 * 2) -- * 6 - whole lb (7680 * 2) -+ * 6 - whole lb (7680 * 2), other crtc must be disabled - * 7 - last 1/4 of lb (1920 * 2) - */ -- if (mode && other_mode) { -- if (mode->hdisplay > other_mode->hdisplay) { -- if (mode->hdisplay > 2560) -- tmp = 1; /* 3/4 */ -- else -- tmp = 0; /* 1/2 */ -- } else if (other_mode->hdisplay > mode->hdisplay) { -- if (other_mode->hdisplay > 2560) -- tmp = 3; /* 1/4 */ -- else -- tmp = 0; /* 1/2 */ -- } else -+ /* this can get tricky if we have two large displays on a paired group -+ * of crtcs. Ideally for multiple large displays we'd assign them to -+ * non-linked crtcs for maximum line buffer allocation. -+ */ -+ if (radeon_crtc->base.enabled && mode) { -+ if (other_mode) - tmp = 0; /* 1/2 */ -- } else if (mode) -- tmp = 2; /* whole */ -- else if (other_mode) -- tmp = 3; /* 1/4 */ -+ else -+ tmp = 2; /* whole */ -+ } else -+ tmp = 0; - - /* second controller of the pair uses second half of the lb */ - if (radeon_crtc->crtc_id % 2) - tmp += 4; - WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp); - -- switch (tmp) { -- case 0: -- case 4: -- default: -- if (ASIC_IS_DCE5(rdev)) -- return 4096 * 2; -- else -- return 3840 * 2; -- case 1: -- case 5: -- if (ASIC_IS_DCE5(rdev)) -- return 6144 * 2; -- else -- return 5760 * 2; -- case 2: -- case 6: -- if (ASIC_IS_DCE5(rdev)) -- return 8192 * 2; -- else -- return 7680 * 2; -- case 3: -- case 7: -- if (ASIC_IS_DCE5(rdev)) -- return 2048 * 2; -- else -- return 1920 * 2; -+ if (radeon_crtc->base.enabled && mode) { -+ switch (tmp) { -+ case 0: -+ case 4: -+ default: -+ if (ASIC_IS_DCE5(rdev)) -+ return 4096 * 2; -+ else -+ return 3840 * 2; -+ case 1: -+ case 5: -+ if (ASIC_IS_DCE5(rdev)) -+ return 6144 * 2; -+ else -+ return 5760 * 2; -+ case 2: -+ case 6: -+ if (ASIC_IS_DCE5(rdev)) -+ return 8192 * 2; -+ else -+ return 7680 * 2; -+ case 3: -+ case 7: -+ if (ASIC_IS_DCE5(rdev)) -+ return 2048 * 2; -+ else -+ return 1920 * 2; -+ } - } -+ -+ /* controller not enabled, so no lb used */ -+ return 0; - } - - static u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev) -@@ -804,7 +797,7 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) - } - } - --static int evergreen_mc_wait_for_idle(struct radeon_device *rdev) -+int evergreen_mc_wait_for_idle(struct radeon_device *rdev) - { - unsigned i; - u32 tmp; -@@ -869,9 +862,15 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) - SYSTEM_ACCESS_MODE_NOT_IN_SYS | - SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | - EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); -- WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); -- WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); -- WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); -+ if (rdev->flags & RADEON_IS_IGP) { -+ WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp); -+ WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp); -+ WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp); -+ } else { -+ WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); -+ WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); -+ WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); -+ } - WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); - WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); - WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); -@@ -957,7 +956,7 @@ void evergreen_agp_enable(struct radeon_device *rdev) - WREG32(VM_CONTEXT1_CNTL, 0); - } - --static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) -+void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) - { - save->vga_control[0] = RREG32(D1VGA_CONTROL); - save->vga_control[1] = RREG32(D2VGA_CONTROL); -@@ -1011,7 +1010,7 @@ static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_sa - WREG32(EVERGREEN_D6VGA_CONTROL, 0); - } - --static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) -+void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) - { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); -@@ -1108,7 +1107,7 @@ static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_ - WREG32(VGA_RENDER_CONTROL, save->vga_render_control); - } - --static void evergreen_mc_program(struct radeon_device *rdev) -+void evergreen_mc_program(struct radeon_device *rdev) - { - struct evergreen_mc_save save; - u32 tmp; -@@ -2576,7 +2575,7 @@ void evergreen_irq_disable(struct radeon_device *rdev) - evergreen_disable_interrupt_state(rdev); - } - --static void evergreen_irq_suspend(struct radeon_device *rdev) -+void evergreen_irq_suspend(struct radeon_device *rdev) - { - evergreen_irq_disable(rdev); - r600_rlc_stop(rdev); -@@ -2587,7 +2586,7 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) - u32 wptr, tmp; - - if (rdev->wb.enabled) -- wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]; -+ wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); - else - wptr = RREG32(IH_RB_WPTR); - -@@ -2899,7 +2898,7 @@ static int evergreen_startup(struct radeon_device *rdev) - return r; - } - } -- r = btc_mc_load_microcode(rdev); -+ r = ni_mc_load_microcode(rdev); - if (r) { - DRM_ERROR("Failed to load MC firmware!\n"); - return r; -@@ -2930,11 +2929,6 @@ static int evergreen_startup(struct radeon_device *rdev) - rdev->asic->copy = NULL; - dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); - } -- /* XXX: ontario has problems blitting to gart at the moment */ -- if (rdev->family == CHIP_PALM) { -- rdev->asic->copy = NULL; -- radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); -- } - - /* allocate wb buffer */ - r = radeon_wb_init(rdev); -@@ -2981,7 +2975,7 @@ int evergreen_resume(struct radeon_device *rdev) - - r = evergreen_startup(rdev); - if (r) { -- DRM_ERROR("r600 startup failed on resume\n"); -+ DRM_ERROR("evergreen startup failed on resume\n"); - return r; - } - -@@ -3061,7 +3055,7 @@ int evergreen_init(struct radeon_device *rdev) - } - /* Must be an ATOMBIOS */ - if (!rdev->is_atom_bios) { -- dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); -+ dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n"); - return -EINVAL; - } - r = radeon_atombios_init(rdev); -diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c -index 345a75a..5e4f9f8 100644 ---- a/drivers/gpu/drm/radeon/evergreen_cs.c -+++ b/drivers/gpu/drm/radeon/evergreen_cs.c -@@ -29,6 +29,7 @@ - #include "radeon.h" - #include "evergreend.h" - #include "evergreen_reg_safe.h" -+#include "cayman_reg_safe.h" - - static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, - struct radeon_cs_reloc **cs_reloc); -@@ -425,18 +426,28 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 - { - struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; - struct radeon_cs_reloc *reloc; -- u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); -+ u32 last_reg; - u32 m, i, tmp, *ib; - int r; - -+ if (p->rdev->family >= CHIP_CAYMAN) -+ last_reg = ARRAY_SIZE(cayman_reg_safe_bm); -+ else -+ last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); -+ - i = (reg >> 7); - if (i > last_reg) { - dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); - return -EINVAL; - } - m = 1 << ((reg >> 2) & 31); -- if (!(evergreen_reg_safe_bm[i] & m)) -- return 0; -+ if (p->rdev->family >= CHIP_CAYMAN) { -+ if (!(cayman_reg_safe_bm[i] & m)) -+ return 0; -+ } else { -+ if (!(evergreen_reg_safe_bm[i] & m)) -+ return 0; -+ } - ib = p->ib->ptr; - switch (reg) { - /* force following reg to 0 in an attemp to disable out buffer -@@ -468,12 +479,42 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 - case SQ_VSTMP_RING_ITEMSIZE: - case VGT_TF_RING_SIZE: - /* get value to populate the IB don't remove */ -- tmp =radeon_get_ib_value(p, idx); -- ib[idx] = 0; -+ /*tmp =radeon_get_ib_value(p, idx); -+ ib[idx] = 0;*/ -+ break; -+ case SQ_ESGS_RING_BASE: -+ case SQ_GSVS_RING_BASE: -+ case SQ_ESTMP_RING_BASE: -+ case SQ_GSTMP_RING_BASE: -+ case SQ_HSTMP_RING_BASE: -+ case SQ_LSTMP_RING_BASE: -+ case SQ_PSTMP_RING_BASE: -+ case SQ_VSTMP_RING_BASE: -+ r = evergreen_cs_packet_next_reloc(p, &reloc); -+ if (r) { -+ dev_warn(p->dev, "bad SET_CONTEXT_REG " -+ "0x%04X\n", reg); -+ return -EINVAL; -+ } -+ ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); - break; - case DB_DEPTH_CONTROL: - track->db_depth_control = radeon_get_ib_value(p, idx); - break; -+ case CAYMAN_DB_EQAA: -+ if (p->rdev->family < CHIP_CAYMAN) { -+ dev_warn(p->dev, "bad SET_CONTEXT_REG " -+ "0x%04X\n", reg); -+ return -EINVAL; -+ } -+ break; -+ case CAYMAN_DB_DEPTH_INFO: -+ if (p->rdev->family < CHIP_CAYMAN) { -+ dev_warn(p->dev, "bad SET_CONTEXT_REG " -+ "0x%04X\n", reg); -+ return -EINVAL; -+ } -+ break; - case DB_Z_INFO: - r = evergreen_cs_packet_next_reloc(p, &reloc); - if (r) { -@@ -559,9 +600,23 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3 - track->cb_shader_mask = radeon_get_ib_value(p, idx); - break; - case PA_SC_AA_CONFIG: -+ if (p->rdev->family >= CHIP_CAYMAN) { -+ dev_warn(p->dev, "bad SET_CONTEXT_REG " -+ "0x%04X\n", reg); -+ return -EINVAL; -+ } - tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; - track->nsamples = 1 << tmp; - break; -+ case CAYMAN_PA_SC_AA_CONFIG: -+ if (p->rdev->family < CHIP_CAYMAN) { -+ dev_warn(p->dev, "bad SET_CONTEXT_REG " -+ "0x%04X\n", reg); -+ return -EINVAL; -+ } -+ tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK; -+ track->nsamples = 1 << tmp; -+ break; - case CB_COLOR0_VIEW: - case CB_COLOR1_VIEW: - case CB_COLOR2_VIEW: -@@ -942,6 +997,37 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, - idx_value = radeon_get_ib_value(p, idx); - - switch (pkt->opcode) { -+ case PACKET3_SET_PREDICATION: -+ { -+ int pred_op; -+ int tmp; -+ if (pkt->count != 1) { -+ DRM_ERROR("bad SET PREDICATION\n"); -+ return -EINVAL; -+ } -+ -+ tmp = radeon_get_ib_value(p, idx + 1); -+ pred_op = (tmp >> 16) & 0x7; -+ -+ /* for the clear predicate operation */ -+ if (pred_op == 0) -+ return 0; -+ -+ if (pred_op > 2) { -+ DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); -+ return -EINVAL; -+ } -+ -+ r = evergreen_cs_packet_next_reloc(p, &reloc); -+ if (r) { -+ DRM_ERROR("bad SET PREDICATION\n"); -+ return -EINVAL; -+ } -+ -+ ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); -+ ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); -+ } -+ break; - case PACKET3_CONTEXT_CONTROL: - if (pkt->count != 1) { - DRM_ERROR("bad CONTEXT_CONTROL\n"); -@@ -956,6 +1042,16 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, - return -EINVAL; - } - break; -+ case CAYMAN_PACKET3_DEALLOC_STATE: -+ if (p->rdev->family < CHIP_CAYMAN) { -+ DRM_ERROR("bad PACKET3_DEALLOC_STATE\n"); -+ return -EINVAL; -+ } -+ if (pkt->count) { -+ DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); -+ return -EINVAL; -+ } -+ break; - case PACKET3_INDEX_BASE: - if (pkt->count != 1) { - DRM_ERROR("bad INDEX_BASE\n"); -diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h -index eb4acf4..9453384 100644 ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -221,6 +221,11 @@ - #define MC_VM_MD_L1_TLB0_CNTL 0x2654 - #define MC_VM_MD_L1_TLB1_CNTL 0x2658 - #define MC_VM_MD_L1_TLB2_CNTL 0x265C -+ -+#define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C -+#define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 -+#define FUS_MC_VM_MD_L1_TLB2_CNTL 0x2664 -+ - #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C - #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 - #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 -@@ -755,13 +760,21 @@ - - #define SQ_CONST_MEM_BASE 0x8df8 - -+#define SQ_ESGS_RING_BASE 0x8c40 - #define SQ_ESGS_RING_SIZE 0x8c44 -+#define SQ_GSVS_RING_BASE 0x8c48 - #define SQ_GSVS_RING_SIZE 0x8c4c -+#define SQ_ESTMP_RING_BASE 0x8c50 - #define SQ_ESTMP_RING_SIZE 0x8c54 -+#define SQ_GSTMP_RING_BASE 0x8c58 - #define SQ_GSTMP_RING_SIZE 0x8c5c -+#define SQ_VSTMP_RING_BASE 0x8c60 - #define SQ_VSTMP_RING_SIZE 0x8c64 -+#define SQ_PSTMP_RING_BASE 0x8c68 - #define SQ_PSTMP_RING_SIZE 0x8c6c -+#define SQ_LSTMP_RING_BASE 0x8e10 - #define SQ_LSTMP_RING_SIZE 0x8e14 -+#define SQ_HSTMP_RING_BASE 0x8e18 - #define SQ_HSTMP_RING_SIZE 0x8e1c - #define VGT_TF_RING_SIZE 0x8988 - -@@ -1093,5 +1106,14 @@ - #define SQ_TEX_RESOURCE_WORD6_0 0x30018 - #define SQ_TEX_RESOURCE_WORD7_0 0x3001c - -+/* cayman 3D regs */ -+#define CAYMAN_VGT_OFFCHIP_LDS_BASE 0x89B0 -+#define CAYMAN_DB_EQAA 0x28804 -+#define CAYMAN_DB_DEPTH_INFO 0x2803C -+#define CAYMAN_PA_SC_AA_CONFIG 0x28BE0 -+#define CAYMAN_MSAA_NUM_SAMPLES_SHIFT 0 -+#define CAYMAN_MSAA_NUM_SAMPLES_MASK 0x7 -+/* cayman packet3 addition */ -+#define CAYMAN_PACKET3_DEALLOC_STATE 0x14 - - #endif -diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c -index 5e0bef8..8c199c4 100644 ---- a/drivers/gpu/drm/radeon/ni.c -+++ b/drivers/gpu/drm/radeon/ni.c -@@ -31,12 +31,25 @@ - #include "nid.h" - #include "atom.h" - #include "ni_reg.h" -+#include "cayman_blit_shaders.h" -+ -+extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); -+extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); -+extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); -+extern void evergreen_mc_program(struct radeon_device *rdev); -+extern void evergreen_irq_suspend(struct radeon_device *rdev); -+extern int evergreen_mc_init(struct radeon_device *rdev); - - #define EVERGREEN_PFP_UCODE_SIZE 1120 - #define EVERGREEN_PM4_UCODE_SIZE 1376 - #define EVERGREEN_RLC_UCODE_SIZE 768 - #define BTC_MC_UCODE_SIZE 6024 - -+#define CAYMAN_PFP_UCODE_SIZE 2176 -+#define CAYMAN_PM4_UCODE_SIZE 2176 -+#define CAYMAN_RLC_UCODE_SIZE 1024 -+#define CAYMAN_MC_UCODE_SIZE 6037 -+ - /* Firmware Names */ - MODULE_FIRMWARE("radeon/BARTS_pfp.bin"); - MODULE_FIRMWARE("radeon/BARTS_me.bin"); -@@ -48,6 +61,10 @@ MODULE_FIRMWARE("radeon/TURKS_mc.bin"); - MODULE_FIRMWARE("radeon/CAICOS_pfp.bin"); - MODULE_FIRMWARE("radeon/CAICOS_me.bin"); - MODULE_FIRMWARE("radeon/CAICOS_mc.bin"); -+MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin"); -+MODULE_FIRMWARE("radeon/CAYMAN_me.bin"); -+MODULE_FIRMWARE("radeon/CAYMAN_mc.bin"); -+MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin"); - - #define BTC_IO_MC_REGS_SIZE 29 - -@@ -147,12 +164,44 @@ static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { - {0x0000009f, 0x00916a00} - }; - --int btc_mc_load_microcode(struct radeon_device *rdev) -+static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { -+ {0x00000077, 0xff010100}, -+ {0x00000078, 0x00000000}, -+ {0x00000079, 0x00001434}, -+ {0x0000007a, 0xcc08ec08}, -+ {0x0000007b, 0x00040000}, -+ {0x0000007c, 0x000080c0}, -+ {0x0000007d, 0x09000000}, -+ {0x0000007e, 0x00210404}, -+ {0x00000081, 0x08a8e800}, -+ {0x00000082, 0x00030444}, -+ {0x00000083, 0x00000000}, -+ {0x00000085, 0x00000001}, -+ {0x00000086, 0x00000002}, -+ {0x00000087, 0x48490000}, -+ {0x00000088, 0x20244647}, -+ {0x00000089, 0x00000005}, -+ {0x0000008b, 0x66030000}, -+ {0x0000008c, 0x00006603}, -+ {0x0000008d, 0x00000100}, -+ {0x0000008f, 0x00001c0a}, -+ {0x00000090, 0xff000001}, -+ {0x00000094, 0x00101101}, -+ {0x00000095, 0x00000fff}, -+ {0x00000096, 0x00116fff}, -+ {0x00000097, 0x60010000}, -+ {0x00000098, 0x10010000}, -+ {0x00000099, 0x00006000}, -+ {0x0000009a, 0x00001000}, -+ {0x0000009f, 0x00976b00} -+}; -+ -+int ni_mc_load_microcode(struct radeon_device *rdev) - { - const __be32 *fw_data; - u32 mem_type, running, blackout = 0; - u32 *io_mc_regs; -- int i; -+ int i, ucode_size, regs_size; - - if (!rdev->mc_fw) - return -EINVAL; -@@ -160,13 +209,24 @@ int btc_mc_load_microcode(struct radeon_device *rdev) - switch (rdev->family) { - case CHIP_BARTS: - io_mc_regs = (u32 *)&barts_io_mc_regs; -+ ucode_size = BTC_MC_UCODE_SIZE; -+ regs_size = BTC_IO_MC_REGS_SIZE; - break; - case CHIP_TURKS: - io_mc_regs = (u32 *)&turks_io_mc_regs; -+ ucode_size = BTC_MC_UCODE_SIZE; -+ regs_size = BTC_IO_MC_REGS_SIZE; - break; - case CHIP_CAICOS: - default: - io_mc_regs = (u32 *)&caicos_io_mc_regs; -+ ucode_size = BTC_MC_UCODE_SIZE; -+ regs_size = BTC_IO_MC_REGS_SIZE; -+ break; -+ case CHIP_CAYMAN: -+ io_mc_regs = (u32 *)&cayman_io_mc_regs; -+ ucode_size = CAYMAN_MC_UCODE_SIZE; -+ regs_size = BTC_IO_MC_REGS_SIZE; - break; - } - -@@ -184,13 +244,13 @@ int btc_mc_load_microcode(struct radeon_device *rdev) - WREG32(MC_SEQ_SUP_CNTL, 0x00000010); - - /* load mc io regs */ -- for (i = 0; i < BTC_IO_MC_REGS_SIZE; i++) { -+ for (i = 0; i < regs_size; i++) { - WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]); - WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]); - } - /* load the MC ucode */ - fw_data = (const __be32 *)rdev->mc_fw->data; -- for (i = 0; i < BTC_MC_UCODE_SIZE; i++) -+ for (i = 0; i < ucode_size; i++) - WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++)); - - /* put the engine back into the active state */ -@@ -231,23 +291,38 @@ int ni_init_microcode(struct radeon_device *rdev) - case CHIP_BARTS: - chip_name = "BARTS"; - rlc_chip_name = "BTC"; -+ pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; -+ me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; -+ rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; -+ mc_req_size = BTC_MC_UCODE_SIZE * 4; - break; - case CHIP_TURKS: - chip_name = "TURKS"; - rlc_chip_name = "BTC"; -+ pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; -+ me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; -+ rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; -+ mc_req_size = BTC_MC_UCODE_SIZE * 4; - break; - case CHIP_CAICOS: - chip_name = "CAICOS"; - rlc_chip_name = "BTC"; -+ pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; -+ me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; -+ rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; -+ mc_req_size = BTC_MC_UCODE_SIZE * 4; -+ break; -+ case CHIP_CAYMAN: -+ chip_name = "CAYMAN"; -+ rlc_chip_name = "CAYMAN"; -+ pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4; -+ me_req_size = CAYMAN_PM4_UCODE_SIZE * 4; -+ rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4; -+ mc_req_size = CAYMAN_MC_UCODE_SIZE * 4; - break; - default: BUG(); - } - -- pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; -- me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; -- rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; -- mc_req_size = BTC_MC_UCODE_SIZE * 4; -- - DRM_INFO("Loading %s Microcode\n", chip_name); - - snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); -@@ -314,3 +389,1204 @@ out: - return err; - } - -+/* -+ * Core functions -+ */ -+static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, -+ u32 num_tile_pipes, -+ u32 num_backends_per_asic, -+ u32 *backend_disable_mask_per_asic, -+ u32 num_shader_engines) -+{ -+ u32 backend_map = 0; -+ u32 enabled_backends_mask = 0; -+ u32 enabled_backends_count = 0; -+ u32 num_backends_per_se; -+ u32 cur_pipe; -+ u32 swizzle_pipe[CAYMAN_MAX_PIPES]; -+ u32 cur_backend = 0; -+ u32 i; -+ bool force_no_swizzle; -+ -+ /* force legal values */ -+ if (num_tile_pipes < 1) -+ num_tile_pipes = 1; -+ if (num_tile_pipes > rdev->config.cayman.max_tile_pipes) -+ num_tile_pipes = rdev->config.cayman.max_tile_pipes; -+ if (num_shader_engines < 1) -+ num_shader_engines = 1; -+ if (num_shader_engines > rdev->config.cayman.max_shader_engines) -+ num_shader_engines = rdev->config.cayman.max_shader_engines; -+ if (num_backends_per_asic > num_shader_engines) -+ num_backends_per_asic = num_shader_engines; -+ if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) -+ num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; -+ -+ /* make sure we have the same number of backends per se */ -+ num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); -+ /* set up the number of backends per se */ -+ num_backends_per_se = num_backends_per_asic / num_shader_engines; -+ if (num_backends_per_se > rdev->config.cayman.max_backends_per_se) { -+ num_backends_per_se = rdev->config.cayman.max_backends_per_se; -+ num_backends_per_asic = num_backends_per_se * num_shader_engines; -+ } -+ -+ /* create enable mask and count for enabled backends */ -+ for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { -+ if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { -+ enabled_backends_mask |= (1 << i); -+ ++enabled_backends_count; -+ } -+ if (enabled_backends_count == num_backends_per_asic) -+ break; -+ } -+ -+ /* force the backends mask to match the current number of backends */ -+ if (enabled_backends_count != num_backends_per_asic) { -+ u32 this_backend_enabled; -+ u32 shader_engine; -+ u32 backend_per_se; -+ -+ enabled_backends_mask = 0; -+ enabled_backends_count = 0; -+ *backend_disable_mask_per_asic = CAYMAN_MAX_BACKENDS_MASK; -+ for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { -+ /* calc the current se */ -+ shader_engine = i / rdev->config.cayman.max_backends_per_se; -+ /* calc the backend per se */ -+ backend_per_se = i % rdev->config.cayman.max_backends_per_se; -+ /* default to not enabled */ -+ this_backend_enabled = 0; -+ if ((shader_engine < num_shader_engines) && -+ (backend_per_se < num_backends_per_se)) -+ this_backend_enabled = 1; -+ if (this_backend_enabled) { -+ enabled_backends_mask |= (1 << i); -+ *backend_disable_mask_per_asic &= ~(1 << i); -+ ++enabled_backends_count; -+ } -+ } -+ } -+ -+ -+ memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES); -+ switch (rdev->family) { -+ case CHIP_CAYMAN: -+ force_no_swizzle = true; -+ break; -+ default: -+ force_no_swizzle = false; -+ break; -+ } -+ if (force_no_swizzle) { -+ bool last_backend_enabled = false; -+ -+ force_no_swizzle = false; -+ for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) { -+ if (((enabled_backends_mask >> i) & 1) == 1) { -+ if (last_backend_enabled) -+ force_no_swizzle = true; -+ last_backend_enabled = true; -+ } else -+ last_backend_enabled = false; -+ } -+ } -+ -+ switch (num_tile_pipes) { -+ case 1: -+ case 3: -+ case 5: -+ case 7: -+ DRM_ERROR("odd number of pipes!\n"); -+ break; -+ case 2: -+ swizzle_pipe[0] = 0; -+ swizzle_pipe[1] = 1; -+ break; -+ case 4: -+ if (force_no_swizzle) { -+ swizzle_pipe[0] = 0; -+ swizzle_pipe[1] = 1; -+ swizzle_pipe[2] = 2; -+ swizzle_pipe[3] = 3; -+ } else { -+ swizzle_pipe[0] = 0; -+ swizzle_pipe[1] = 2; -+ swizzle_pipe[2] = 1; -+ swizzle_pipe[3] = 3; -+ } -+ break; -+ case 6: -+ if (force_no_swizzle) { -+ swizzle_pipe[0] = 0; -+ swizzle_pipe[1] = 1; -+ swizzle_pipe[2] = 2; -+ swizzle_pipe[3] = 3; -+ swizzle_pipe[4] = 4; -+ swizzle_pipe[5] = 5; -+ } else { -+ swizzle_pipe[0] = 0; -+ swizzle_pipe[1] = 2; -+ swizzle_pipe[2] = 4; -+ swizzle_pipe[3] = 1; -+ swizzle_pipe[4] = 3; -+ swizzle_pipe[5] = 5; -+ } -+ break; -+ case 8: -+ if (force_no_swizzle) { -+ swizzle_pipe[0] = 0; -+ swizzle_pipe[1] = 1; -+ swizzle_pipe[2] = 2; -+ swizzle_pipe[3] = 3; -+ swizzle_pipe[4] = 4; -+ swizzle_pipe[5] = 5; -+ swizzle_pipe[6] = 6; -+ swizzle_pipe[7] = 7; -+ } else { -+ swizzle_pipe[0] = 0; -+ swizzle_pipe[1] = 2; -+ swizzle_pipe[2] = 4; -+ swizzle_pipe[3] = 6; -+ swizzle_pipe[4] = 1; -+ swizzle_pipe[5] = 3; -+ swizzle_pipe[6] = 5; -+ swizzle_pipe[7] = 7; -+ } -+ break; -+ } -+ -+ for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { -+ while (((1 << cur_backend) & enabled_backends_mask) == 0) -+ cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; -+ -+ backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); -+ -+ cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS; -+ } -+ -+ return backend_map; -+} -+ -+static void cayman_program_channel_remap(struct radeon_device *rdev) -+{ -+ u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp; -+ -+ tmp = RREG32(MC_SHARED_CHMAP); -+ switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { -+ case 0: -+ case 1: -+ case 2: -+ case 3: -+ default: -+ /* default mapping */ -+ mc_shared_chremap = 0x00fac688; -+ break; -+ } -+ -+ switch (rdev->family) { -+ case CHIP_CAYMAN: -+ default: -+ //tcp_chan_steer_lo = 0x54763210 -+ tcp_chan_steer_lo = 0x76543210; -+ tcp_chan_steer_hi = 0x0000ba98; -+ break; -+ } -+ -+ WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo); -+ WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi); -+ WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); -+} -+ -+static u32 cayman_get_disable_mask_per_asic(struct radeon_device *rdev, -+ u32 disable_mask_per_se, -+ u32 max_disable_mask_per_se, -+ u32 num_shader_engines) -+{ -+ u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); -+ u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; -+ -+ if (num_shader_engines == 1) -+ return disable_mask_per_asic; -+ else if (num_shader_engines == 2) -+ return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); -+ else -+ return 0xffffffff; -+} -+ -+static void cayman_gpu_init(struct radeon_device *rdev) -+{ -+ u32 cc_rb_backend_disable = 0; -+ u32 cc_gc_shader_pipe_config; -+ u32 gb_addr_config = 0; -+ u32 mc_shared_chmap, mc_arb_ramcfg; -+ u32 gb_backend_map; -+ u32 cgts_tcc_disable; -+ u32 sx_debug_1; -+ u32 smx_dc_ctl0; -+ u32 gc_user_shader_pipe_config; -+ u32 gc_user_rb_backend_disable; -+ u32 cgts_user_tcc_disable; -+ u32 cgts_sm_ctrl_reg; -+ u32 hdp_host_path_cntl; -+ u32 tmp; -+ int i, j; -+ -+ switch (rdev->family) { -+ case CHIP_CAYMAN: -+ default: -+ rdev->config.cayman.max_shader_engines = 2; -+ rdev->config.cayman.max_pipes_per_simd = 4; -+ rdev->config.cayman.max_tile_pipes = 8; -+ rdev->config.cayman.max_simds_per_se = 12; -+ rdev->config.cayman.max_backends_per_se = 4; -+ rdev->config.cayman.max_texture_channel_caches = 8; -+ rdev->config.cayman.max_gprs = 256; -+ rdev->config.cayman.max_threads = 256; -+ rdev->config.cayman.max_gs_threads = 32; -+ rdev->config.cayman.max_stack_entries = 512; -+ rdev->config.cayman.sx_num_of_sets = 8; -+ rdev->config.cayman.sx_max_export_size = 256; -+ rdev->config.cayman.sx_max_export_pos_size = 64; -+ rdev->config.cayman.sx_max_export_smx_size = 192; -+ rdev->config.cayman.max_hw_contexts = 8; -+ rdev->config.cayman.sq_num_cf_insts = 2; -+ -+ rdev->config.cayman.sc_prim_fifo_size = 0x100; -+ rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30; -+ rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130; -+ break; -+ } -+ -+ /* Initialize HDP */ -+ for (i = 0, j = 0; i < 32; i++, j += 0x18) { -+ WREG32((0x2c14 + j), 0x00000000); -+ WREG32((0x2c18 + j), 0x00000000); -+ WREG32((0x2c1c + j), 0x00000000); -+ WREG32((0x2c20 + j), 0x00000000); -+ WREG32((0x2c24 + j), 0x00000000); -+ } -+ -+ WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); -+ -+ mc_shared_chmap = RREG32(MC_SHARED_CHMAP); -+ mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); -+ -+ cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); -+ cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); -+ cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE); -+ gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); -+ gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); -+ cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); -+ -+ rdev->config.cayman.num_shader_engines = rdev->config.cayman.max_shader_engines; -+ tmp = ((~gc_user_shader_pipe_config) & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; -+ rdev->config.cayman.num_shader_pipes_per_simd = r600_count_pipe_bits(tmp); -+ rdev->config.cayman.num_tile_pipes = rdev->config.cayman.max_tile_pipes; -+ tmp = ((~gc_user_shader_pipe_config) & INACTIVE_SIMDS_MASK) >> INACTIVE_SIMDS_SHIFT; -+ rdev->config.cayman.num_simds_per_se = r600_count_pipe_bits(tmp); -+ tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; -+ rdev->config.cayman.num_backends_per_se = r600_count_pipe_bits(tmp); -+ tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; -+ rdev->config.cayman.backend_disable_mask_per_asic = -+ cayman_get_disable_mask_per_asic(rdev, tmp, CAYMAN_MAX_BACKENDS_PER_SE_MASK, -+ rdev->config.cayman.num_shader_engines); -+ rdev->config.cayman.backend_map = -+ cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, -+ rdev->config.cayman.num_backends_per_se * -+ rdev->config.cayman.num_shader_engines, -+ &rdev->config.cayman.backend_disable_mask_per_asic, -+ rdev->config.cayman.num_shader_engines); -+ tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; -+ rdev->config.cayman.num_texture_channel_caches = r600_count_pipe_bits(tmp); -+ tmp = (mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT; -+ rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; -+ if (rdev->config.cayman.mem_max_burst_length_bytes > 512) -+ rdev->config.cayman.mem_max_burst_length_bytes = 512; -+ tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; -+ rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; -+ if (rdev->config.cayman.mem_row_size_in_kb > 4) -+ rdev->config.cayman.mem_row_size_in_kb = 4; -+ /* XXX use MC settings? */ -+ rdev->config.cayman.shader_engine_tile_size = 32; -+ rdev->config.cayman.num_gpus = 1; -+ rdev->config.cayman.multi_gpu_tile_size = 64; -+ -+ //gb_addr_config = 0x02011003 -+#if 0 -+ gb_addr_config = RREG32(GB_ADDR_CONFIG); -+#else -+ gb_addr_config = 0; -+ switch (rdev->config.cayman.num_tile_pipes) { -+ case 1: -+ default: -+ gb_addr_config |= NUM_PIPES(0); -+ break; -+ case 2: -+ gb_addr_config |= NUM_PIPES(1); -+ break; -+ case 4: -+ gb_addr_config |= NUM_PIPES(2); -+ break; -+ case 8: -+ gb_addr_config |= NUM_PIPES(3); -+ break; -+ } -+ -+ tmp = (rdev->config.cayman.mem_max_burst_length_bytes / 256) - 1; -+ gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); -+ gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.cayman.num_shader_engines - 1); -+ tmp = (rdev->config.cayman.shader_engine_tile_size / 16) - 1; -+ gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); -+ switch (rdev->config.cayman.num_gpus) { -+ case 1: -+ default: -+ gb_addr_config |= NUM_GPUS(0); -+ break; -+ case 2: -+ gb_addr_config |= NUM_GPUS(1); -+ break; -+ case 4: -+ gb_addr_config |= NUM_GPUS(2); -+ break; -+ } -+ switch (rdev->config.cayman.multi_gpu_tile_size) { -+ case 16: -+ gb_addr_config |= MULTI_GPU_TILE_SIZE(0); -+ break; -+ case 32: -+ default: -+ gb_addr_config |= MULTI_GPU_TILE_SIZE(1); -+ break; -+ case 64: -+ gb_addr_config |= MULTI_GPU_TILE_SIZE(2); -+ break; -+ case 128: -+ gb_addr_config |= MULTI_GPU_TILE_SIZE(3); -+ break; -+ } -+ switch (rdev->config.cayman.mem_row_size_in_kb) { -+ case 1: -+ default: -+ gb_addr_config |= ROW_SIZE(0); -+ break; -+ case 2: -+ gb_addr_config |= ROW_SIZE(1); -+ break; -+ case 4: -+ gb_addr_config |= ROW_SIZE(2); -+ break; -+ } -+#endif -+ -+ tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; -+ rdev->config.cayman.num_tile_pipes = (1 << tmp); -+ tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; -+ rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256; -+ tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; -+ rdev->config.cayman.num_shader_engines = tmp + 1; -+ tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; -+ rdev->config.cayman.num_gpus = tmp + 1; -+ tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; -+ rdev->config.cayman.multi_gpu_tile_size = 1 << tmp; -+ tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; -+ rdev->config.cayman.mem_row_size_in_kb = 1 << tmp; -+ -+ //gb_backend_map = 0x76541032; -+#if 0 -+ gb_backend_map = RREG32(GB_BACKEND_MAP); -+#else -+ gb_backend_map = -+ cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes, -+ rdev->config.cayman.num_backends_per_se * -+ rdev->config.cayman.num_shader_engines, -+ &rdev->config.cayman.backend_disable_mask_per_asic, -+ rdev->config.cayman.num_shader_engines); -+#endif -+ /* setup tiling info dword. gb_addr_config is not adequate since it does -+ * not have bank info, so create a custom tiling dword. -+ * bits 3:0 num_pipes -+ * bits 7:4 num_banks -+ * bits 11:8 group_size -+ * bits 15:12 row_size -+ */ -+ rdev->config.cayman.tile_config = 0; -+ switch (rdev->config.cayman.num_tile_pipes) { -+ case 1: -+ default: -+ rdev->config.cayman.tile_config |= (0 << 0); -+ break; -+ case 2: -+ rdev->config.cayman.tile_config |= (1 << 0); -+ break; -+ case 4: -+ rdev->config.cayman.tile_config |= (2 << 0); -+ break; -+ case 8: -+ rdev->config.cayman.tile_config |= (3 << 0); -+ break; -+ } -+ rdev->config.cayman.tile_config |= -+ ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; -+ rdev->config.cayman.tile_config |= -+ (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; -+ rdev->config.cayman.tile_config |= -+ ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; -+ -+ WREG32(GB_BACKEND_MAP, gb_backend_map); -+ WREG32(GB_ADDR_CONFIG, gb_addr_config); -+ WREG32(DMIF_ADDR_CONFIG, gb_addr_config); -+ WREG32(HDP_ADDR_CONFIG, gb_addr_config); -+ -+ cayman_program_channel_remap(rdev); -+ -+ /* primary versions */ -+ WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); -+ WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); -+ WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); -+ -+ WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); -+ WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable); -+ -+ /* user versions */ -+ WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); -+ WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); -+ WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); -+ -+ WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable); -+ WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); -+ -+ /* reprogram the shader complex */ -+ cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG); -+ for (i = 0; i < 16; i++) -+ WREG32(CGTS_SM_CTRL_REG, OVERRIDE); -+ WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg); -+ -+ /* set HW defaults for 3D engine */ -+ WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60)); -+ -+ sx_debug_1 = RREG32(SX_DEBUG_1); -+ sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS; -+ WREG32(SX_DEBUG_1, sx_debug_1); -+ -+ smx_dc_ctl0 = RREG32(SMX_DC_CTL0); -+ smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); -+ smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); -+ WREG32(SMX_DC_CTL0, smx_dc_ctl0); -+ -+ WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE); -+ -+ /* need to be explicitly zero-ed */ -+ WREG32(VGT_OFFCHIP_LDS_BASE, 0); -+ WREG32(SQ_LSTMP_RING_BASE, 0); -+ WREG32(SQ_HSTMP_RING_BASE, 0); -+ WREG32(SQ_ESTMP_RING_BASE, 0); -+ WREG32(SQ_GSTMP_RING_BASE, 0); -+ WREG32(SQ_VSTMP_RING_BASE, 0); -+ WREG32(SQ_PSTMP_RING_BASE, 0); -+ -+ WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO); -+ -+ WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | -+ POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | -+ SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); -+ -+ WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) | -+ SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) | -+ SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size))); -+ -+ -+ WREG32(VGT_NUM_INSTANCES, 1); -+ -+ WREG32(CP_PERFMON_CNTL, 0); -+ -+ WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) | -+ FETCH_FIFO_HIWATER(0x4) | -+ DONE_FIFO_HIWATER(0xe0) | -+ ALU_UPDATE_FIFO_HIWATER(0x8))); -+ -+ WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4)); -+ WREG32(SQ_CONFIG, (VC_ENABLE | -+ EXPORT_SRC_C | -+ GFX_PRIO(0) | -+ CS1_PRIO(0) | -+ CS2_PRIO(1))); -+ WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE); -+ -+ WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | -+ FORCE_EOV_MAX_REZ_CNT(255))); -+ -+ WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) | -+ AUTO_INVLD_EN(ES_AND_GS_AUTO)); -+ -+ WREG32(VGT_GS_VERTEX_REUSE, 16); -+ WREG32(PA_SC_LINE_STIPPLE_STATE, 0); -+ -+ WREG32(CB_PERF_CTR0_SEL_0, 0); -+ WREG32(CB_PERF_CTR0_SEL_1, 0); -+ WREG32(CB_PERF_CTR1_SEL_0, 0); -+ WREG32(CB_PERF_CTR1_SEL_1, 0); -+ WREG32(CB_PERF_CTR2_SEL_0, 0); -+ WREG32(CB_PERF_CTR2_SEL_1, 0); -+ WREG32(CB_PERF_CTR3_SEL_0, 0); -+ WREG32(CB_PERF_CTR3_SEL_1, 0); -+ -+ hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); -+ WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); -+ -+ WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3)); -+ -+ udelay(50); -+} -+ -+/* -+ * GART -+ */ -+void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev) -+{ -+ /* flush hdp cache */ -+ WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); -+ -+ /* bits 0-7 are the VM contexts0-7 */ -+ WREG32(VM_INVALIDATE_REQUEST, 1); -+} -+ -+int cayman_pcie_gart_enable(struct radeon_device *rdev) -+{ -+ int r; -+ -+ if (rdev->gart.table.vram.robj == NULL) { -+ dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); -+ return -EINVAL; -+ } -+ r = radeon_gart_table_vram_pin(rdev); -+ if (r) -+ return r; -+ radeon_gart_restore(rdev); -+ /* Setup TLB control */ -+ WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB | -+ ENABLE_L1_FRAGMENT_PROCESSING | -+ SYSTEM_ACCESS_MODE_NOT_IN_SYS | -+ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); -+ /* Setup L2 cache */ -+ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | -+ ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | -+ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | -+ EFFECTIVE_L2_QUEUE_SIZE(7) | -+ CONTEXT1_IDENTITY_ACCESS_MODE(1)); -+ WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE); -+ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | -+ L2_CACHE_BIGK_FRAGMENT_SIZE(6)); -+ /* setup context0 */ -+ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); -+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); -+ WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); -+ WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, -+ (u32)(rdev->dummy_page.addr >> 12)); -+ WREG32(VM_CONTEXT0_CNTL2, 0); -+ WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | -+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); -+ /* disable context1-7 */ -+ WREG32(VM_CONTEXT1_CNTL2, 0); -+ WREG32(VM_CONTEXT1_CNTL, 0); -+ -+ cayman_pcie_gart_tlb_flush(rdev); -+ rdev->gart.ready = true; -+ return 0; -+} -+ -+void cayman_pcie_gart_disable(struct radeon_device *rdev) -+{ -+ int r; -+ -+ /* Disable all tables */ -+ WREG32(VM_CONTEXT0_CNTL, 0); -+ WREG32(VM_CONTEXT1_CNTL, 0); -+ /* Setup TLB control */ -+ WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING | -+ SYSTEM_ACCESS_MODE_NOT_IN_SYS | -+ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); -+ /* Setup L2 cache */ -+ WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | -+ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE | -+ EFFECTIVE_L2_QUEUE_SIZE(7) | -+ CONTEXT1_IDENTITY_ACCESS_MODE(1)); -+ WREG32(VM_L2_CNTL2, 0); -+ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | -+ L2_CACHE_BIGK_FRAGMENT_SIZE(6)); -+ if (rdev->gart.table.vram.robj) { -+ r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); -+ if (likely(r == 0)) { -+ radeon_bo_kunmap(rdev->gart.table.vram.robj); -+ radeon_bo_unpin(rdev->gart.table.vram.robj); -+ radeon_bo_unreserve(rdev->gart.table.vram.robj); -+ } -+ } -+} -+ -+void cayman_pcie_gart_fini(struct radeon_device *rdev) -+{ -+ cayman_pcie_gart_disable(rdev); -+ radeon_gart_table_vram_free(rdev); -+ radeon_gart_fini(rdev); -+} -+ -+/* -+ * CP. -+ */ -+static void cayman_cp_enable(struct radeon_device *rdev, bool enable) -+{ -+ if (enable) -+ WREG32(CP_ME_CNTL, 0); -+ else { -+ radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); -+ WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); -+ WREG32(SCRATCH_UMSK, 0); -+ } -+} -+ -+static int cayman_cp_load_microcode(struct radeon_device *rdev) -+{ -+ const __be32 *fw_data; -+ int i; -+ -+ if (!rdev->me_fw || !rdev->pfp_fw) -+ return -EINVAL; -+ -+ cayman_cp_enable(rdev, false); -+ -+ fw_data = (const __be32 *)rdev->pfp_fw->data; -+ WREG32(CP_PFP_UCODE_ADDR, 0); -+ for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++) -+ WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); -+ WREG32(CP_PFP_UCODE_ADDR, 0); -+ -+ fw_data = (const __be32 *)rdev->me_fw->data; -+ WREG32(CP_ME_RAM_WADDR, 0); -+ for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++) -+ WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); -+ -+ WREG32(CP_PFP_UCODE_ADDR, 0); -+ WREG32(CP_ME_RAM_WADDR, 0); -+ WREG32(CP_ME_RAM_RADDR, 0); -+ return 0; -+} -+ -+static int cayman_cp_start(struct radeon_device *rdev) -+{ -+ int r, i; -+ -+ r = radeon_ring_lock(rdev, 7); -+ if (r) { -+ DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); -+ return r; -+ } -+ radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); -+ radeon_ring_write(rdev, 0x1); -+ radeon_ring_write(rdev, 0x0); -+ radeon_ring_write(rdev, rdev->config.cayman.max_hw_contexts - 1); -+ radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); -+ radeon_ring_write(rdev, 0); -+ radeon_ring_write(rdev, 0); -+ radeon_ring_unlock_commit(rdev); -+ -+ cayman_cp_enable(rdev, true); -+ -+ r = radeon_ring_lock(rdev, cayman_default_size + 19); -+ if (r) { -+ DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); -+ return r; -+ } -+ -+ /* setup clear context state */ -+ radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); -+ radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE); -+ -+ for (i = 0; i < cayman_default_size; i++) -+ radeon_ring_write(rdev, cayman_default_state[i]); -+ -+ radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0)); -+ radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE); -+ -+ /* set clear context state */ -+ radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); -+ radeon_ring_write(rdev, 0); -+ -+ /* SQ_VTX_BASE_VTX_LOC */ -+ radeon_ring_write(rdev, 0xc0026f00); -+ radeon_ring_write(rdev, 0x00000000); -+ radeon_ring_write(rdev, 0x00000000); -+ radeon_ring_write(rdev, 0x00000000); -+ -+ /* Clear consts */ -+ radeon_ring_write(rdev, 0xc0036f00); -+ radeon_ring_write(rdev, 0x00000bc4); -+ radeon_ring_write(rdev, 0xffffffff); -+ radeon_ring_write(rdev, 0xffffffff); -+ radeon_ring_write(rdev, 0xffffffff); -+ -+ radeon_ring_write(rdev, 0xc0026900); -+ radeon_ring_write(rdev, 0x00000316); -+ radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */ -+ radeon_ring_write(rdev, 0x00000010); /* */ -+ -+ radeon_ring_unlock_commit(rdev); -+ -+ /* XXX init other rings */ -+ -+ return 0; -+} -+ -+static void cayman_cp_fini(struct radeon_device *rdev) -+{ -+ cayman_cp_enable(rdev, false); -+ radeon_ring_fini(rdev); -+} -+ -+int cayman_cp_resume(struct radeon_device *rdev) -+{ -+ u32 tmp; -+ u32 rb_bufsz; -+ int r; -+ -+ /* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */ -+ WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP | -+ SOFT_RESET_PA | -+ SOFT_RESET_SH | -+ SOFT_RESET_VGT | -+ SOFT_RESET_SX)); -+ RREG32(GRBM_SOFT_RESET); -+ mdelay(15); -+ WREG32(GRBM_SOFT_RESET, 0); -+ RREG32(GRBM_SOFT_RESET); -+ -+ WREG32(CP_SEM_WAIT_TIMER, 0x4); -+ -+ /* Set the write pointer delay */ -+ WREG32(CP_RB_WPTR_DELAY, 0); -+ -+ WREG32(CP_DEBUG, (1 << 27)); -+ -+ /* ring 0 - compute and gfx */ -+ /* Set ring buffer size */ -+ rb_bufsz = drm_order(rdev->cp.ring_size / 8); -+ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; -+#ifdef __BIG_ENDIAN -+ tmp |= BUF_SWAP_32BIT; -+#endif -+ WREG32(CP_RB0_CNTL, tmp); -+ -+ /* Initialize the ring buffer's read and write pointers */ -+ WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA); -+ WREG32(CP_RB0_WPTR, 0); -+ -+ /* set the wb address wether it's enabled or not */ -+ WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); -+ WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); -+ WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); -+ -+ if (rdev->wb.enabled) -+ WREG32(SCRATCH_UMSK, 0xff); -+ else { -+ tmp |= RB_NO_UPDATE; -+ WREG32(SCRATCH_UMSK, 0); -+ } -+ -+ mdelay(1); -+ WREG32(CP_RB0_CNTL, tmp); -+ -+ WREG32(CP_RB0_BASE, rdev->cp.gpu_addr >> 8); -+ -+ rdev->cp.rptr = RREG32(CP_RB0_RPTR); -+ rdev->cp.wptr = RREG32(CP_RB0_WPTR); -+ -+ /* ring1 - compute only */ -+ /* Set ring buffer size */ -+ rb_bufsz = drm_order(rdev->cp1.ring_size / 8); -+ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; -+#ifdef __BIG_ENDIAN -+ tmp |= BUF_SWAP_32BIT; -+#endif -+ WREG32(CP_RB1_CNTL, tmp); -+ -+ /* Initialize the ring buffer's read and write pointers */ -+ WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA); -+ WREG32(CP_RB1_WPTR, 0); -+ -+ /* set the wb address wether it's enabled or not */ -+ WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); -+ WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); -+ -+ mdelay(1); -+ WREG32(CP_RB1_CNTL, tmp); -+ -+ WREG32(CP_RB1_BASE, rdev->cp1.gpu_addr >> 8); -+ -+ rdev->cp1.rptr = RREG32(CP_RB1_RPTR); -+ rdev->cp1.wptr = RREG32(CP_RB1_WPTR); -+ -+ /* ring2 - compute only */ -+ /* Set ring buffer size */ -+ rb_bufsz = drm_order(rdev->cp2.ring_size / 8); -+ tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; -+#ifdef __BIG_ENDIAN -+ tmp |= BUF_SWAP_32BIT; -+#endif -+ WREG32(CP_RB2_CNTL, tmp); -+ -+ /* Initialize the ring buffer's read and write pointers */ -+ WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA); -+ WREG32(CP_RB2_WPTR, 0); -+ -+ /* set the wb address wether it's enabled or not */ -+ WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); -+ WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); -+ -+ mdelay(1); -+ WREG32(CP_RB2_CNTL, tmp); -+ -+ WREG32(CP_RB2_BASE, rdev->cp2.gpu_addr >> 8); -+ -+ rdev->cp2.rptr = RREG32(CP_RB2_RPTR); -+ rdev->cp2.wptr = RREG32(CP_RB2_WPTR); -+ -+ /* start the rings */ -+ cayman_cp_start(rdev); -+ rdev->cp.ready = true; -+ rdev->cp1.ready = true; -+ rdev->cp2.ready = true; -+ /* this only test cp0 */ -+ r = radeon_ring_test(rdev); -+ if (r) { -+ rdev->cp.ready = false; -+ rdev->cp1.ready = false; -+ rdev->cp2.ready = false; -+ return r; -+ } -+ -+ return 0; -+} -+ -+bool cayman_gpu_is_lockup(struct radeon_device *rdev) -+{ -+ u32 srbm_status; -+ u32 grbm_status; -+ u32 grbm_status_se0, grbm_status_se1; -+ struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup; -+ int r; -+ -+ srbm_status = RREG32(SRBM_STATUS); -+ grbm_status = RREG32(GRBM_STATUS); -+ grbm_status_se0 = RREG32(GRBM_STATUS_SE0); -+ grbm_status_se1 = RREG32(GRBM_STATUS_SE1); -+ if (!(grbm_status & GUI_ACTIVE)) { -+ r100_gpu_lockup_update(lockup, &rdev->cp); -+ return false; -+ } -+ /* force CP activities */ -+ r = radeon_ring_lock(rdev, 2); -+ if (!r) { -+ /* PACKET2 NOP */ -+ radeon_ring_write(rdev, 0x80000000); -+ radeon_ring_write(rdev, 0x80000000); -+ radeon_ring_unlock_commit(rdev); -+ } -+ /* XXX deal with CP0,1,2 */ -+ rdev->cp.rptr = RREG32(CP_RB0_RPTR); -+ return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp); -+} -+ -+static int cayman_gpu_soft_reset(struct radeon_device *rdev) -+{ -+ struct evergreen_mc_save save; -+ u32 grbm_reset = 0; -+ -+ if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) -+ return 0; -+ -+ dev_info(rdev->dev, "GPU softreset \n"); -+ dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", -+ RREG32(GRBM_STATUS)); -+ dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", -+ RREG32(GRBM_STATUS_SE0)); -+ dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", -+ RREG32(GRBM_STATUS_SE1)); -+ dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", -+ RREG32(SRBM_STATUS)); -+ evergreen_mc_stop(rdev, &save); -+ if (evergreen_mc_wait_for_idle(rdev)) { -+ dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); -+ } -+ /* Disable CP parsing/prefetching */ -+ WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); -+ -+ /* reset all the gfx blocks */ -+ grbm_reset = (SOFT_RESET_CP | -+ SOFT_RESET_CB | -+ SOFT_RESET_DB | -+ SOFT_RESET_GDS | -+ SOFT_RESET_PA | -+ SOFT_RESET_SC | -+ SOFT_RESET_SPI | -+ SOFT_RESET_SH | -+ SOFT_RESET_SX | -+ SOFT_RESET_TC | -+ SOFT_RESET_TA | -+ SOFT_RESET_VGT | -+ SOFT_RESET_IA); -+ -+ dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); -+ WREG32(GRBM_SOFT_RESET, grbm_reset); -+ (void)RREG32(GRBM_SOFT_RESET); -+ udelay(50); -+ WREG32(GRBM_SOFT_RESET, 0); -+ (void)RREG32(GRBM_SOFT_RESET); -+ /* Wait a little for things to settle down */ -+ udelay(50); -+ dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", -+ RREG32(GRBM_STATUS)); -+ dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", -+ RREG32(GRBM_STATUS_SE0)); -+ dev_info(rdev->dev, " GRBM_STATUS_SE1=0x%08X\n", -+ RREG32(GRBM_STATUS_SE1)); -+ dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", -+ RREG32(SRBM_STATUS)); -+ evergreen_mc_resume(rdev, &save); -+ return 0; -+} -+ -+int cayman_asic_reset(struct radeon_device *rdev) -+{ -+ return cayman_gpu_soft_reset(rdev); -+} -+ -+static int cayman_startup(struct radeon_device *rdev) -+{ -+ int r; -+ -+ if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { -+ r = ni_init_microcode(rdev); -+ if (r) { -+ DRM_ERROR("Failed to load firmware!\n"); -+ return r; -+ } -+ } -+ r = ni_mc_load_microcode(rdev); -+ if (r) { -+ DRM_ERROR("Failed to load MC firmware!\n"); -+ return r; -+ } -+ -+ evergreen_mc_program(rdev); -+ r = cayman_pcie_gart_enable(rdev); -+ if (r) -+ return r; -+ cayman_gpu_init(rdev); -+ -+#if 0 -+ r = cayman_blit_init(rdev); -+ if (r) { -+ cayman_blit_fini(rdev); -+ rdev->asic->copy = NULL; -+ dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); -+ } -+#endif -+ -+ /* allocate wb buffer */ -+ r = radeon_wb_init(rdev); -+ if (r) -+ return r; -+ -+ /* Enable IRQ */ -+ r = r600_irq_init(rdev); -+ if (r) { -+ DRM_ERROR("radeon: IH init failed (%d).\n", r); -+ radeon_irq_kms_fini(rdev); -+ return r; -+ } -+ evergreen_irq_set(rdev); -+ -+ r = radeon_ring_init(rdev, rdev->cp.ring_size); -+ if (r) -+ return r; -+ r = cayman_cp_load_microcode(rdev); -+ if (r) -+ return r; -+ r = cayman_cp_resume(rdev); -+ if (r) -+ return r; -+ -+ return 0; -+} -+ -+int cayman_resume(struct radeon_device *rdev) -+{ -+ int r; -+ -+ /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, -+ * posting will perform necessary task to bring back GPU into good -+ * shape. -+ */ -+ /* post card */ -+ atom_asic_init(rdev->mode_info.atom_context); -+ -+ r = cayman_startup(rdev); -+ if (r) { -+ DRM_ERROR("cayman startup failed on resume\n"); -+ return r; -+ } -+ -+ r = r600_ib_test(rdev); -+ if (r) { -+ DRM_ERROR("radeon: failled testing IB (%d).\n", r); -+ return r; -+ } -+ -+ return r; -+ -+} -+ -+int cayman_suspend(struct radeon_device *rdev) -+{ -+ /* int r; */ -+ -+ /* FIXME: we should wait for ring to be empty */ -+ cayman_cp_enable(rdev, false); -+ rdev->cp.ready = false; -+ evergreen_irq_suspend(rdev); -+ radeon_wb_disable(rdev); -+ cayman_pcie_gart_disable(rdev); -+ -+#if 0 -+ /* unpin shaders bo */ -+ r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); -+ if (likely(r == 0)) { -+ radeon_bo_unpin(rdev->r600_blit.shader_obj); -+ radeon_bo_unreserve(rdev->r600_blit.shader_obj); -+ } -+#endif -+ return 0; -+} -+ -+/* Plan is to move initialization in that function and use -+ * helper function so that radeon_device_init pretty much -+ * do nothing more than calling asic specific function. This -+ * should also allow to remove a bunch of callback function -+ * like vram_info. -+ */ -+int cayman_init(struct radeon_device *rdev) -+{ -+ int r; -+ -+ /* This don't do much */ -+ r = radeon_gem_init(rdev); -+ if (r) -+ return r; -+ /* Read BIOS */ -+ if (!radeon_get_bios(rdev)) { -+ if (ASIC_IS_AVIVO(rdev)) -+ return -EINVAL; -+ } -+ /* Must be an ATOMBIOS */ -+ if (!rdev->is_atom_bios) { -+ dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); -+ return -EINVAL; -+ } -+ r = radeon_atombios_init(rdev); -+ if (r) -+ return r; -+ -+ /* Post card if necessary */ -+ if (!radeon_card_posted(rdev)) { -+ if (!rdev->bios) { -+ dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); -+ return -EINVAL; -+ } -+ DRM_INFO("GPU not posted. posting now...\n"); -+ atom_asic_init(rdev->mode_info.atom_context); -+ } -+ /* Initialize scratch registers */ -+ r600_scratch_init(rdev); -+ /* Initialize surface registers */ -+ radeon_surface_init(rdev); -+ /* Initialize clocks */ -+ radeon_get_clock_info(rdev->ddev); -+ /* Fence driver */ -+ r = radeon_fence_driver_init(rdev); -+ if (r) -+ return r; -+ /* initialize memory controller */ -+ r = evergreen_mc_init(rdev); -+ if (r) -+ return r; -+ /* Memory manager */ -+ r = radeon_bo_init(rdev); -+ if (r) -+ return r; -+ -+ r = radeon_irq_kms_init(rdev); -+ if (r) -+ return r; -+ -+ rdev->cp.ring_obj = NULL; -+ r600_ring_init(rdev, 1024 * 1024); -+ -+ rdev->ih.ring_obj = NULL; -+ r600_ih_ring_init(rdev, 64 * 1024); -+ -+ r = r600_pcie_gart_init(rdev); -+ if (r) -+ return r; -+ -+ rdev->accel_working = true; -+ r = cayman_startup(rdev); -+ if (r) { -+ dev_err(rdev->dev, "disabling GPU acceleration\n"); -+ cayman_cp_fini(rdev); -+ r600_irq_fini(rdev); -+ radeon_wb_fini(rdev); -+ radeon_irq_kms_fini(rdev); -+ cayman_pcie_gart_fini(rdev); -+ rdev->accel_working = false; -+ } -+ if (rdev->accel_working) { -+ r = radeon_ib_pool_init(rdev); -+ if (r) { -+ DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); -+ rdev->accel_working = false; -+ } -+ r = r600_ib_test(rdev); -+ if (r) { -+ DRM_ERROR("radeon: failed testing IB (%d).\n", r); -+ rdev->accel_working = false; -+ } -+ } -+ -+ /* Don't start up if the MC ucode is missing. -+ * The default clocks and voltages before the MC ucode -+ * is loaded are not suffient for advanced operations. -+ */ -+ if (!rdev->mc_fw) { -+ DRM_ERROR("radeon: MC ucode required for NI+.\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+void cayman_fini(struct radeon_device *rdev) -+{ -+ /* cayman_blit_fini(rdev); */ -+ cayman_cp_fini(rdev); -+ r600_irq_fini(rdev); -+ radeon_wb_fini(rdev); -+ radeon_irq_kms_fini(rdev); -+ cayman_pcie_gart_fini(rdev); -+ radeon_gem_fini(rdev); -+ radeon_fence_driver_fini(rdev); -+ radeon_bo_fini(rdev); -+ radeon_atombios_fini(rdev); -+ kfree(rdev->bios); -+ rdev->bios = NULL; -+} -+ -diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h -index f7b4453..0f9a08b 100644 ---- a/drivers/gpu/drm/radeon/nid.h -+++ b/drivers/gpu/drm/radeon/nid.h -@@ -24,7 +24,101 @@ - #ifndef NI_H - #define NI_H - -+#define CAYMAN_MAX_SH_GPRS 256 -+#define CAYMAN_MAX_TEMP_GPRS 16 -+#define CAYMAN_MAX_SH_THREADS 256 -+#define CAYMAN_MAX_SH_STACK_ENTRIES 4096 -+#define CAYMAN_MAX_FRC_EOV_CNT 16384 -+#define CAYMAN_MAX_BACKENDS 8 -+#define CAYMAN_MAX_BACKENDS_MASK 0xFF -+#define CAYMAN_MAX_BACKENDS_PER_SE_MASK 0xF -+#define CAYMAN_MAX_SIMDS 16 -+#define CAYMAN_MAX_SIMDS_MASK 0xFFFF -+#define CAYMAN_MAX_SIMDS_PER_SE_MASK 0xFFF -+#define CAYMAN_MAX_PIPES 8 -+#define CAYMAN_MAX_PIPES_MASK 0xFF -+#define CAYMAN_MAX_LDS_NUM 0xFFFF -+#define CAYMAN_MAX_TCC 16 -+#define CAYMAN_MAX_TCC_MASK 0xFF -+ -+#define DMIF_ADDR_CONFIG 0xBD4 -+#define SRBM_STATUS 0x0E50 -+ -+#define VM_CONTEXT0_REQUEST_RESPONSE 0x1470 -+#define REQUEST_TYPE(x) (((x) & 0xf) << 0) -+#define RESPONSE_TYPE_MASK 0x000000F0 -+#define RESPONSE_TYPE_SHIFT 4 -+#define VM_L2_CNTL 0x1400 -+#define ENABLE_L2_CACHE (1 << 0) -+#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1) -+#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9) -+#define ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE (1 << 10) -+#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 14) -+#define CONTEXT1_IDENTITY_ACCESS_MODE(x) (((x) & 3) << 18) -+/* CONTEXT1_IDENTITY_ACCESS_MODE -+ * 0 physical = logical -+ * 1 logical via context1 page table -+ * 2 inside identity aperture use translation, outside physical = logical -+ * 3 inside identity aperture physical = logical, outside use translation -+ */ -+#define VM_L2_CNTL2 0x1404 -+#define INVALIDATE_ALL_L1_TLBS (1 << 0) -+#define INVALIDATE_L2_CACHE (1 << 1) -+#define VM_L2_CNTL3 0x1408 -+#define BANK_SELECT(x) ((x) << 0) -+#define CACHE_UPDATE_MODE(x) ((x) << 6) -+#define L2_CACHE_BIGK_ASSOCIATIVITY (1 << 20) -+#define L2_CACHE_BIGK_FRAGMENT_SIZE(x) ((x) << 15) -+#define VM_L2_STATUS 0x140C -+#define L2_BUSY (1 << 0) -+#define VM_CONTEXT0_CNTL 0x1410 -+#define ENABLE_CONTEXT (1 << 0) -+#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) -+#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) -+#define VM_CONTEXT1_CNTL 0x1414 -+#define VM_CONTEXT0_CNTL2 0x1430 -+#define VM_CONTEXT1_CNTL2 0x1434 -+#define VM_INVALIDATE_REQUEST 0x1478 -+#define VM_INVALIDATE_RESPONSE 0x147c -+#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1518 -+#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x151c -+#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C -+#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C -+#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C -+ -+#define MC_SHARED_CHMAP 0x2004 -+#define NOOFCHAN_SHIFT 12 -+#define NOOFCHAN_MASK 0x00003000 -+#define MC_SHARED_CHREMAP 0x2008 -+ -+#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 -+#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 -+#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C -+#define MC_VM_MX_L1_TLB_CNTL 0x2064 -+#define ENABLE_L1_TLB (1 << 0) -+#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) -+#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 3) -+#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 3) -+#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) -+#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 3) -+#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) -+#define ENABLE_ADVANCED_DRIVER_MODEL (1 << 6) -+ - #define MC_SHARED_BLACKOUT_CNTL 0x20ac -+#define MC_ARB_RAMCFG 0x2760 -+#define NOOFBANK_SHIFT 0 -+#define NOOFBANK_MASK 0x00000003 -+#define NOOFRANK_SHIFT 2 -+#define NOOFRANK_MASK 0x00000004 -+#define NOOFROWS_SHIFT 3 -+#define NOOFROWS_MASK 0x00000038 -+#define NOOFCOLS_SHIFT 6 -+#define NOOFCOLS_MASK 0x000000C0 -+#define CHANSIZE_SHIFT 8 -+#define CHANSIZE_MASK 0x00000100 -+#define BURSTLENGTH_SHIFT 9 -+#define BURSTLENGTH_MASK 0x00000200 -+#define CHANSIZE_OVERRIDE (1 << 11) - #define MC_SEQ_SUP_CNTL 0x28c8 - #define RUN_MASK (1 << 0) - #define MC_SEQ_SUP_PGM 0x28cc -@@ -37,5 +131,406 @@ - #define MC_SEQ_IO_DEBUG_INDEX 0x2a44 - #define MC_SEQ_IO_DEBUG_DATA 0x2a48 - -+#define HDP_HOST_PATH_CNTL 0x2C00 -+#define HDP_NONSURFACE_BASE 0x2C04 -+#define HDP_NONSURFACE_INFO 0x2C08 -+#define HDP_NONSURFACE_SIZE 0x2C0C -+#define HDP_ADDR_CONFIG 0x2F48 -+ -+#define CC_SYS_RB_BACKEND_DISABLE 0x3F88 -+#define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C -+#define CGTS_SYS_TCC_DISABLE 0x3F90 -+#define CGTS_USER_SYS_TCC_DISABLE 0x3F94 -+ -+#define CONFIG_MEMSIZE 0x5428 -+ -+#define HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 -+#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0 -+ -+#define GRBM_CNTL 0x8000 -+#define GRBM_READ_TIMEOUT(x) ((x) << 0) -+#define GRBM_STATUS 0x8010 -+#define CMDFIFO_AVAIL_MASK 0x0000000F -+#define RING2_RQ_PENDING (1 << 4) -+#define SRBM_RQ_PENDING (1 << 5) -+#define RING1_RQ_PENDING (1 << 6) -+#define CF_RQ_PENDING (1 << 7) -+#define PF_RQ_PENDING (1 << 8) -+#define GDS_DMA_RQ_PENDING (1 << 9) -+#define GRBM_EE_BUSY (1 << 10) -+#define SX_CLEAN (1 << 11) -+#define DB_CLEAN (1 << 12) -+#define CB_CLEAN (1 << 13) -+#define TA_BUSY (1 << 14) -+#define GDS_BUSY (1 << 15) -+#define VGT_BUSY_NO_DMA (1 << 16) -+#define VGT_BUSY (1 << 17) -+#define IA_BUSY_NO_DMA (1 << 18) -+#define IA_BUSY (1 << 19) -+#define SX_BUSY (1 << 20) -+#define SH_BUSY (1 << 21) -+#define SPI_BUSY (1 << 22) -+#define SC_BUSY (1 << 24) -+#define PA_BUSY (1 << 25) -+#define DB_BUSY (1 << 26) -+#define CP_COHERENCY_BUSY (1 << 28) -+#define CP_BUSY (1 << 29) -+#define CB_BUSY (1 << 30) -+#define GUI_ACTIVE (1 << 31) -+#define GRBM_STATUS_SE0 0x8014 -+#define GRBM_STATUS_SE1 0x8018 -+#define SE_SX_CLEAN (1 << 0) -+#define SE_DB_CLEAN (1 << 1) -+#define SE_CB_CLEAN (1 << 2) -+#define SE_VGT_BUSY (1 << 23) -+#define SE_PA_BUSY (1 << 24) -+#define SE_TA_BUSY (1 << 25) -+#define SE_SX_BUSY (1 << 26) -+#define SE_SPI_BUSY (1 << 27) -+#define SE_SH_BUSY (1 << 28) -+#define SE_SC_BUSY (1 << 29) -+#define SE_DB_BUSY (1 << 30) -+#define SE_CB_BUSY (1 << 31) -+#define GRBM_SOFT_RESET 0x8020 -+#define SOFT_RESET_CP (1 << 0) -+#define SOFT_RESET_CB (1 << 1) -+#define SOFT_RESET_DB (1 << 3) -+#define SOFT_RESET_GDS (1 << 4) -+#define SOFT_RESET_PA (1 << 5) -+#define SOFT_RESET_SC (1 << 6) -+#define SOFT_RESET_SPI (1 << 8) -+#define SOFT_RESET_SH (1 << 9) -+#define SOFT_RESET_SX (1 << 10) -+#define SOFT_RESET_TC (1 << 11) -+#define SOFT_RESET_TA (1 << 12) -+#define SOFT_RESET_VGT (1 << 14) -+#define SOFT_RESET_IA (1 << 15) -+ -+#define SCRATCH_REG0 0x8500 -+#define SCRATCH_REG1 0x8504 -+#define SCRATCH_REG2 0x8508 -+#define SCRATCH_REG3 0x850C -+#define SCRATCH_REG4 0x8510 -+#define SCRATCH_REG5 0x8514 -+#define SCRATCH_REG6 0x8518 -+#define SCRATCH_REG7 0x851C -+#define SCRATCH_UMSK 0x8540 -+#define SCRATCH_ADDR 0x8544 -+#define CP_SEM_WAIT_TIMER 0x85BC -+#define CP_ME_CNTL 0x86D8 -+#define CP_ME_HALT (1 << 28) -+#define CP_PFP_HALT (1 << 26) -+#define CP_RB2_RPTR 0x86f8 -+#define CP_RB1_RPTR 0x86fc -+#define CP_RB0_RPTR 0x8700 -+#define CP_RB_WPTR_DELAY 0x8704 -+#define CP_MEQ_THRESHOLDS 0x8764 -+#define MEQ1_START(x) ((x) << 0) -+#define MEQ2_START(x) ((x) << 8) -+#define CP_PERFMON_CNTL 0x87FC -+ -+#define VGT_CACHE_INVALIDATION 0x88C4 -+#define CACHE_INVALIDATION(x) ((x) << 0) -+#define VC_ONLY 0 -+#define TC_ONLY 1 -+#define VC_AND_TC 2 -+#define AUTO_INVLD_EN(x) ((x) << 6) -+#define NO_AUTO 0 -+#define ES_AUTO 1 -+#define GS_AUTO 2 -+#define ES_AND_GS_AUTO 3 -+#define VGT_GS_VERTEX_REUSE 0x88D4 -+ -+#define CC_GC_SHADER_PIPE_CONFIG 0x8950 -+#define GC_USER_SHADER_PIPE_CONFIG 0x8954 -+#define INACTIVE_QD_PIPES(x) ((x) << 8) -+#define INACTIVE_QD_PIPES_MASK 0x0000FF00 -+#define INACTIVE_QD_PIPES_SHIFT 8 -+#define INACTIVE_SIMDS(x) ((x) << 16) -+#define INACTIVE_SIMDS_MASK 0xFFFF0000 -+#define INACTIVE_SIMDS_SHIFT 16 -+ -+#define VGT_PRIMITIVE_TYPE 0x8958 -+#define VGT_NUM_INSTANCES 0x8974 -+#define VGT_TF_RING_SIZE 0x8988 -+#define VGT_OFFCHIP_LDS_BASE 0x89b4 -+ -+#define PA_SC_LINE_STIPPLE_STATE 0x8B10 -+#define PA_CL_ENHANCE 0x8A14 -+#define CLIP_VTX_REORDER_ENA (1 << 0) -+#define NUM_CLIP_SEQ(x) ((x) << 1) -+#define PA_SC_FIFO_SIZE 0x8BCC -+#define SC_PRIM_FIFO_SIZE(x) ((x) << 0) -+#define SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) -+#define SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) -+#define PA_SC_FORCE_EOV_MAX_CNTS 0x8B24 -+#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) -+#define FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) -+ -+#define SQ_CONFIG 0x8C00 -+#define VC_ENABLE (1 << 0) -+#define EXPORT_SRC_C (1 << 1) -+#define GFX_PRIO(x) ((x) << 2) -+#define CS1_PRIO(x) ((x) << 4) -+#define CS2_PRIO(x) ((x) << 6) -+#define SQ_GPR_RESOURCE_MGMT_1 0x8C04 -+#define NUM_PS_GPRS(x) ((x) << 0) -+#define NUM_VS_GPRS(x) ((x) << 16) -+#define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) -+#define SQ_ESGS_RING_SIZE 0x8c44 -+#define SQ_GSVS_RING_SIZE 0x8c4c -+#define SQ_ESTMP_RING_BASE 0x8c50 -+#define SQ_ESTMP_RING_SIZE 0x8c54 -+#define SQ_GSTMP_RING_BASE 0x8c58 -+#define SQ_GSTMP_RING_SIZE 0x8c5c -+#define SQ_VSTMP_RING_BASE 0x8c60 -+#define SQ_VSTMP_RING_SIZE 0x8c64 -+#define SQ_PSTMP_RING_BASE 0x8c68 -+#define SQ_PSTMP_RING_SIZE 0x8c6c -+#define SQ_MS_FIFO_SIZES 0x8CF0 -+#define CACHE_FIFO_SIZE(x) ((x) << 0) -+#define FETCH_FIFO_HIWATER(x) ((x) << 8) -+#define DONE_FIFO_HIWATER(x) ((x) << 16) -+#define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) -+#define SQ_LSTMP_RING_BASE 0x8e10 -+#define SQ_LSTMP_RING_SIZE 0x8e14 -+#define SQ_HSTMP_RING_BASE 0x8e18 -+#define SQ_HSTMP_RING_SIZE 0x8e1c -+#define SQ_DYN_GPR_CNTL_PS_FLUSH_REQ 0x8D8C -+#define DYN_GPR_ENABLE (1 << 8) -+#define SQ_CONST_MEM_BASE 0x8df8 -+ -+#define SX_EXPORT_BUFFER_SIZES 0x900C -+#define COLOR_BUFFER_SIZE(x) ((x) << 0) -+#define POSITION_BUFFER_SIZE(x) ((x) << 8) -+#define SMX_BUFFER_SIZE(x) ((x) << 16) -+#define SX_DEBUG_1 0x9058 -+#define ENABLE_NEW_SMX_ADDRESS (1 << 16) -+ -+#define SPI_CONFIG_CNTL 0x9100 -+#define GPR_WRITE_PRIORITY(x) ((x) << 0) -+#define SPI_CONFIG_CNTL_1 0x913C -+#define VTX_DONE_DELAY(x) ((x) << 0) -+#define INTERP_ONE_PRIM_PER_ROW (1 << 4) -+#define CRC_SIMD_ID_WADDR_DISABLE (1 << 8) -+ -+#define CGTS_TCC_DISABLE 0x9148 -+#define CGTS_USER_TCC_DISABLE 0x914C -+#define TCC_DISABLE_MASK 0xFFFF0000 -+#define TCC_DISABLE_SHIFT 16 -+#define CGTS_SM_CTRL_REG 0x915C -+#define OVERRIDE (1 << 21) -+ -+#define TA_CNTL_AUX 0x9508 -+#define DISABLE_CUBE_WRAP (1 << 0) -+#define DISABLE_CUBE_ANISO (1 << 1) -+ -+#define TCP_CHAN_STEER_LO 0x960c -+#define TCP_CHAN_STEER_HI 0x9610 -+ -+#define CC_RB_BACKEND_DISABLE 0x98F4 -+#define BACKEND_DISABLE(x) ((x) << 16) -+#define GB_ADDR_CONFIG 0x98F8 -+#define NUM_PIPES(x) ((x) << 0) -+#define NUM_PIPES_MASK 0x00000007 -+#define NUM_PIPES_SHIFT 0 -+#define PIPE_INTERLEAVE_SIZE(x) ((x) << 4) -+#define PIPE_INTERLEAVE_SIZE_MASK 0x00000070 -+#define PIPE_INTERLEAVE_SIZE_SHIFT 4 -+#define BANK_INTERLEAVE_SIZE(x) ((x) << 8) -+#define NUM_SHADER_ENGINES(x) ((x) << 12) -+#define NUM_SHADER_ENGINES_MASK 0x00003000 -+#define NUM_SHADER_ENGINES_SHIFT 12 -+#define SHADER_ENGINE_TILE_SIZE(x) ((x) << 16) -+#define SHADER_ENGINE_TILE_SIZE_MASK 0x00070000 -+#define SHADER_ENGINE_TILE_SIZE_SHIFT 16 -+#define NUM_GPUS(x) ((x) << 20) -+#define NUM_GPUS_MASK 0x00700000 -+#define NUM_GPUS_SHIFT 20 -+#define MULTI_GPU_TILE_SIZE(x) ((x) << 24) -+#define MULTI_GPU_TILE_SIZE_MASK 0x03000000 -+#define MULTI_GPU_TILE_SIZE_SHIFT 24 -+#define ROW_SIZE(x) ((x) << 28) -+#define ROW_SIZE_MASK 0x30000007 -+#define ROW_SIZE_SHIFT 28 -+#define NUM_LOWER_PIPES(x) ((x) << 30) -+#define NUM_LOWER_PIPES_MASK 0x40000000 -+#define NUM_LOWER_PIPES_SHIFT 30 -+#define GB_BACKEND_MAP 0x98FC -+ -+#define CB_PERF_CTR0_SEL_0 0x9A20 -+#define CB_PERF_CTR0_SEL_1 0x9A24 -+#define CB_PERF_CTR1_SEL_0 0x9A28 -+#define CB_PERF_CTR1_SEL_1 0x9A2C -+#define CB_PERF_CTR2_SEL_0 0x9A30 -+#define CB_PERF_CTR2_SEL_1 0x9A34 -+#define CB_PERF_CTR3_SEL_0 0x9A38 -+#define CB_PERF_CTR3_SEL_1 0x9A3C -+ -+#define GC_USER_RB_BACKEND_DISABLE 0x9B7C -+#define BACKEND_DISABLE_MASK 0x00FF0000 -+#define BACKEND_DISABLE_SHIFT 16 -+ -+#define SMX_DC_CTL0 0xA020 -+#define USE_HASH_FUNCTION (1 << 0) -+#define NUMBER_OF_SETS(x) ((x) << 1) -+#define FLUSH_ALL_ON_EVENT (1 << 10) -+#define STALL_ON_EVENT (1 << 11) -+#define SMX_EVENT_CTL 0xA02C -+#define ES_FLUSH_CTL(x) ((x) << 0) -+#define GS_FLUSH_CTL(x) ((x) << 3) -+#define ACK_FLUSH_CTL(x) ((x) << 6) -+#define SYNC_FLUSH_CTL (1 << 8) -+ -+#define CP_RB0_BASE 0xC100 -+#define CP_RB0_CNTL 0xC104 -+#define RB_BUFSZ(x) ((x) << 0) -+#define RB_BLKSZ(x) ((x) << 8) -+#define RB_NO_UPDATE (1 << 27) -+#define RB_RPTR_WR_ENA (1 << 31) -+#define BUF_SWAP_32BIT (2 << 16) -+#define CP_RB0_RPTR_ADDR 0xC10C -+#define CP_RB0_RPTR_ADDR_HI 0xC110 -+#define CP_RB0_WPTR 0xC114 -+#define CP_RB1_BASE 0xC180 -+#define CP_RB1_CNTL 0xC184 -+#define CP_RB1_RPTR_ADDR 0xC188 -+#define CP_RB1_RPTR_ADDR_HI 0xC18C -+#define CP_RB1_WPTR 0xC190 -+#define CP_RB2_BASE 0xC194 -+#define CP_RB2_CNTL 0xC198 -+#define CP_RB2_RPTR_ADDR 0xC19C -+#define CP_RB2_RPTR_ADDR_HI 0xC1A0 -+#define CP_RB2_WPTR 0xC1A4 -+#define CP_PFP_UCODE_ADDR 0xC150 -+#define CP_PFP_UCODE_DATA 0xC154 -+#define CP_ME_RAM_RADDR 0xC158 -+#define CP_ME_RAM_WADDR 0xC15C -+#define CP_ME_RAM_DATA 0xC160 -+#define CP_DEBUG 0xC1FC -+ -+/* -+ * PM4 -+ */ -+#define PACKET_TYPE0 0 -+#define PACKET_TYPE1 1 -+#define PACKET_TYPE2 2 -+#define PACKET_TYPE3 3 -+ -+#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) -+#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) -+#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2) -+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) -+#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \ -+ (((reg) >> 2) & 0xFFFF) | \ -+ ((n) & 0x3FFF) << 16) -+#define CP_PACKET2 0x80000000 -+#define PACKET2_PAD_SHIFT 0 -+#define PACKET2_PAD_MASK (0x3fffffff << 0) -+ -+#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) -+ -+#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ -+ (((op) & 0xFF) << 8) | \ -+ ((n) & 0x3FFF) << 16) -+ -+/* Packet 3 types */ -+#define PACKET3_NOP 0x10 -+#define PACKET3_SET_BASE 0x11 -+#define PACKET3_CLEAR_STATE 0x12 -+#define PACKET3_INDEX_BUFFER_SIZE 0x13 -+#define PACKET3_DEALLOC_STATE 0x14 -+#define PACKET3_DISPATCH_DIRECT 0x15 -+#define PACKET3_DISPATCH_INDIRECT 0x16 -+#define PACKET3_INDIRECT_BUFFER_END 0x17 -+#define PACKET3_SET_PREDICATION 0x20 -+#define PACKET3_REG_RMW 0x21 -+#define PACKET3_COND_EXEC 0x22 -+#define PACKET3_PRED_EXEC 0x23 -+#define PACKET3_DRAW_INDIRECT 0x24 -+#define PACKET3_DRAW_INDEX_INDIRECT 0x25 -+#define PACKET3_INDEX_BASE 0x26 -+#define PACKET3_DRAW_INDEX_2 0x27 -+#define PACKET3_CONTEXT_CONTROL 0x28 -+#define PACKET3_DRAW_INDEX_OFFSET 0x29 -+#define PACKET3_INDEX_TYPE 0x2A -+#define PACKET3_DRAW_INDEX 0x2B -+#define PACKET3_DRAW_INDEX_AUTO 0x2D -+#define PACKET3_DRAW_INDEX_IMMD 0x2E -+#define PACKET3_NUM_INSTANCES 0x2F -+#define PACKET3_DRAW_INDEX_MULTI_AUTO 0x30 -+#define PACKET3_INDIRECT_BUFFER 0x32 -+#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34 -+#define PACKET3_DRAW_INDEX_OFFSET_2 0x35 -+#define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 -+#define PACKET3_WRITE_DATA 0x37 -+#define PACKET3_MEM_SEMAPHORE 0x39 -+#define PACKET3_MPEG_INDEX 0x3A -+#define PACKET3_WAIT_REG_MEM 0x3C -+#define PACKET3_MEM_WRITE 0x3D -+#define PACKET3_SURFACE_SYNC 0x43 -+# define PACKET3_CB0_DEST_BASE_ENA (1 << 6) -+# define PACKET3_CB1_DEST_BASE_ENA (1 << 7) -+# define PACKET3_CB2_DEST_BASE_ENA (1 << 8) -+# define PACKET3_CB3_DEST_BASE_ENA (1 << 9) -+# define PACKET3_CB4_DEST_BASE_ENA (1 << 10) -+# define PACKET3_CB5_DEST_BASE_ENA (1 << 11) -+# define PACKET3_CB6_DEST_BASE_ENA (1 << 12) -+# define PACKET3_CB7_DEST_BASE_ENA (1 << 13) -+# define PACKET3_DB_DEST_BASE_ENA (1 << 14) -+# define PACKET3_CB8_DEST_BASE_ENA (1 << 15) -+# define PACKET3_CB9_DEST_BASE_ENA (1 << 16) -+# define PACKET3_CB10_DEST_BASE_ENA (1 << 17) -+# define PACKET3_CB11_DEST_BASE_ENA (1 << 18) -+# define PACKET3_FULL_CACHE_ENA (1 << 20) -+# define PACKET3_TC_ACTION_ENA (1 << 23) -+# define PACKET3_CB_ACTION_ENA (1 << 25) -+# define PACKET3_DB_ACTION_ENA (1 << 26) -+# define PACKET3_SH_ACTION_ENA (1 << 27) -+# define PACKET3_SX_ACTION_ENA (1 << 28) -+#define PACKET3_ME_INITIALIZE 0x44 -+#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) -+#define PACKET3_COND_WRITE 0x45 -+#define PACKET3_EVENT_WRITE 0x46 -+#define PACKET3_EVENT_WRITE_EOP 0x47 -+#define PACKET3_EVENT_WRITE_EOS 0x48 -+#define PACKET3_PREAMBLE_CNTL 0x4A -+# define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE (2 << 28) -+# define PACKET3_PREAMBLE_END_CLEAR_STATE (3 << 28) -+#define PACKET3_ALU_PS_CONST_BUFFER_COPY 0x4C -+#define PACKET3_ALU_VS_CONST_BUFFER_COPY 0x4D -+#define PACKET3_ALU_PS_CONST_UPDATE 0x4E -+#define PACKET3_ALU_VS_CONST_UPDATE 0x4F -+#define PACKET3_ONE_REG_WRITE 0x57 -+#define PACKET3_SET_CONFIG_REG 0x68 -+#define PACKET3_SET_CONFIG_REG_START 0x00008000 -+#define PACKET3_SET_CONFIG_REG_END 0x0000ac00 -+#define PACKET3_SET_CONTEXT_REG 0x69 -+#define PACKET3_SET_CONTEXT_REG_START 0x00028000 -+#define PACKET3_SET_CONTEXT_REG_END 0x00029000 -+#define PACKET3_SET_ALU_CONST 0x6A -+/* alu const buffers only; no reg file */ -+#define PACKET3_SET_BOOL_CONST 0x6B -+#define PACKET3_SET_BOOL_CONST_START 0x0003a500 -+#define PACKET3_SET_BOOL_CONST_END 0x0003a518 -+#define PACKET3_SET_LOOP_CONST 0x6C -+#define PACKET3_SET_LOOP_CONST_START 0x0003a200 -+#define PACKET3_SET_LOOP_CONST_END 0x0003a500 -+#define PACKET3_SET_RESOURCE 0x6D -+#define PACKET3_SET_RESOURCE_START 0x00030000 -+#define PACKET3_SET_RESOURCE_END 0x00038000 -+#define PACKET3_SET_SAMPLER 0x6E -+#define PACKET3_SET_SAMPLER_START 0x0003c000 -+#define PACKET3_SET_SAMPLER_END 0x0003c600 -+#define PACKET3_SET_CTL_CONST 0x6F -+#define PACKET3_SET_CTL_CONST_START 0x0003cff0 -+#define PACKET3_SET_CTL_CONST_END 0x0003ff0c -+#define PACKET3_SET_RESOURCE_OFFSET 0x70 -+#define PACKET3_SET_ALU_CONST_VS 0x71 -+#define PACKET3_SET_ALU_CONST_DI 0x72 -+#define PACKET3_SET_CONTEXT_REG_INDIRECT 0x73 -+#define PACKET3_SET_RESOURCE_INDIRECT 0x74 -+#define PACKET3_SET_APPEND_CNT 0x75 -+ - #endif - -diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c -index 9b3fad2..70e9fb0 100644 ---- a/drivers/gpu/drm/radeon/r600.c -+++ b/drivers/gpu/drm/radeon/r600.c -@@ -47,6 +47,7 @@ - #define EVERGREEN_PFP_UCODE_SIZE 1120 - #define EVERGREEN_PM4_UCODE_SIZE 1376 - #define EVERGREEN_RLC_UCODE_SIZE 768 -+#define CAYMAN_RLC_UCODE_SIZE 1024 - - /* Firmware Names */ - MODULE_FIRMWARE("radeon/R600_pfp.bin"); -@@ -586,7 +587,7 @@ void r600_pm_misc(struct radeon_device *rdev) - - if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { - if (voltage->voltage != rdev->pm.current_vddc) { -- radeon_atom_set_voltage(rdev, voltage->voltage); -+ radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); - rdev->pm.current_vddc = voltage->voltage; - DRM_DEBUG_DRIVER("Setting: v: %d\n", voltage->voltage); - } -@@ -2820,13 +2821,20 @@ static int r600_rlc_init(struct radeon_device *rdev) - WREG32(RLC_HB_CNTL, 0); - WREG32(RLC_HB_RPTR, 0); - WREG32(RLC_HB_WPTR, 0); -- WREG32(RLC_HB_WPTR_LSB_ADDR, 0); -- WREG32(RLC_HB_WPTR_MSB_ADDR, 0); -+ if (rdev->family <= CHIP_CAICOS) { -+ WREG32(RLC_HB_WPTR_LSB_ADDR, 0); -+ WREG32(RLC_HB_WPTR_MSB_ADDR, 0); -+ } - WREG32(RLC_MC_CNTL, 0); - WREG32(RLC_UCODE_CNTL, 0); - - fw_data = (const __be32 *)rdev->rlc_fw->data; -- if (rdev->family >= CHIP_CEDAR) { -+ if (rdev->family >= CHIP_CAYMAN) { -+ for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) { -+ WREG32(RLC_UCODE_ADDR, i); -+ WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); -+ } -+ } else if (rdev->family >= CHIP_CEDAR) { - for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) { - WREG32(RLC_UCODE_ADDR, i); - WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); -@@ -3227,7 +3235,7 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) - u32 wptr, tmp; - - if (rdev->wb.enabled) -- wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]; -+ wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); - else - wptr = RREG32(IH_RB_WPTR); - -diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c -index 153095f..0a0848f 100644 ---- a/drivers/gpu/drm/radeon/r600_cs.c -+++ b/drivers/gpu/drm/radeon/r600_cs.c -@@ -71,75 +71,167 @@ struct r600_cs_track { - u64 db_bo_mc; - }; - -+#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc } -+#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc } -+#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0 } -+#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc } -+#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0 } -+#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc } -+#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0 } -+#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16, vc } -+ -+struct gpu_formats { -+ unsigned blockwidth; -+ unsigned blockheight; -+ unsigned blocksize; -+ unsigned valid_color; -+}; -+ -+static const struct gpu_formats color_formats_table[] = { -+ /* 8 bit */ -+ FMT_8_BIT(V_038004_COLOR_8, 1), -+ FMT_8_BIT(V_038004_COLOR_4_4, 1), -+ FMT_8_BIT(V_038004_COLOR_3_3_2, 1), -+ FMT_8_BIT(V_038004_FMT_1, 0), -+ -+ /* 16-bit */ -+ FMT_16_BIT(V_038004_COLOR_16, 1), -+ FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1), -+ FMT_16_BIT(V_038004_COLOR_8_8, 1), -+ FMT_16_BIT(V_038004_COLOR_5_6_5, 1), -+ FMT_16_BIT(V_038004_COLOR_6_5_5, 1), -+ FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1), -+ FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1), -+ FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1), -+ -+ /* 24-bit */ -+ FMT_24_BIT(V_038004_FMT_8_8_8), -+ -+ /* 32-bit */ -+ FMT_32_BIT(V_038004_COLOR_32, 1), -+ FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1), -+ FMT_32_BIT(V_038004_COLOR_16_16, 1), -+ FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1), -+ FMT_32_BIT(V_038004_COLOR_8_24, 1), -+ FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1), -+ FMT_32_BIT(V_038004_COLOR_24_8, 1), -+ FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1), -+ FMT_32_BIT(V_038004_COLOR_10_11_11, 1), -+ FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1), -+ FMT_32_BIT(V_038004_COLOR_11_11_10, 1), -+ FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1), -+ FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1), -+ FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1), -+ FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1), -+ FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0), -+ FMT_32_BIT(V_038004_FMT_32_AS_8, 0), -+ FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0), -+ -+ /* 48-bit */ -+ FMT_48_BIT(V_038004_FMT_16_16_16), -+ FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT), -+ -+ /* 64-bit */ -+ FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1), -+ FMT_64_BIT(V_038004_COLOR_32_32, 1), -+ FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1), -+ FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1), -+ FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1), -+ -+ FMT_96_BIT(V_038004_FMT_32_32_32), -+ FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT), -+ -+ /* 128-bit */ -+ FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1), -+ FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1), -+ -+ [V_038004_FMT_GB_GR] = { 2, 1, 4, 0 }, -+ [V_038004_FMT_BG_RG] = { 2, 1, 4, 0 }, -+ -+ /* block compressed formats */ -+ [V_038004_FMT_BC1] = { 4, 4, 8, 0 }, -+ [V_038004_FMT_BC2] = { 4, 4, 16, 0 }, -+ [V_038004_FMT_BC3] = { 4, 4, 16, 0 }, -+ [V_038004_FMT_BC4] = { 4, 4, 8, 0 }, -+ [V_038004_FMT_BC5] = { 4, 4, 16, 0}, -+ -+}; -+ -+static inline bool fmt_is_valid_color(u32 format) -+{ -+ if (format >= ARRAY_SIZE(color_formats_table)) -+ return false; -+ -+ if (color_formats_table[format].valid_color) -+ return true; -+ -+ return false; -+} -+ -+static inline bool fmt_is_valid_texture(u32 format) -+{ -+ if (format >= ARRAY_SIZE(color_formats_table)) -+ return false; -+ -+ if (color_formats_table[format].blockwidth > 0) -+ return true; -+ -+ return false; -+} -+ -+static inline int fmt_get_blocksize(u32 format) -+{ -+ if (format >= ARRAY_SIZE(color_formats_table)) -+ return 0; -+ -+ return color_formats_table[format].blocksize; -+} -+ -+static inline int fmt_get_nblocksx(u32 format, u32 w) -+{ -+ unsigned bw; -+ -+ if (format >= ARRAY_SIZE(color_formats_table)) -+ return 0; -+ -+ bw = color_formats_table[format].blockwidth; -+ if (bw == 0) -+ return 0; -+ -+ return (w + bw - 1) / bw; -+} -+ -+static inline int fmt_get_nblocksy(u32 format, u32 h) -+{ -+ unsigned bh; -+ -+ if (format >= ARRAY_SIZE(color_formats_table)) -+ return 0; -+ -+ bh = color_formats_table[format].blockheight; -+ if (bh == 0) -+ return 0; -+ -+ return (h + bh - 1) / bh; -+} -+ - static inline int r600_bpe_from_format(u32 *bpe, u32 format) - { -- switch (format) { -- case V_038004_COLOR_8: -- case V_038004_COLOR_4_4: -- case V_038004_COLOR_3_3_2: -- case V_038004_FMT_1: -- *bpe = 1; -- break; -- case V_038004_COLOR_16: -- case V_038004_COLOR_16_FLOAT: -- case V_038004_COLOR_8_8: -- case V_038004_COLOR_5_6_5: -- case V_038004_COLOR_6_5_5: -- case V_038004_COLOR_1_5_5_5: -- case V_038004_COLOR_4_4_4_4: -- case V_038004_COLOR_5_5_5_1: -- *bpe = 2; -- break; -- case V_038004_FMT_8_8_8: -- *bpe = 3; -- break; -- case V_038004_COLOR_32: -- case V_038004_COLOR_32_FLOAT: -- case V_038004_COLOR_16_16: -- case V_038004_COLOR_16_16_FLOAT: -- case V_038004_COLOR_8_24: -- case V_038004_COLOR_8_24_FLOAT: -- case V_038004_COLOR_24_8: -- case V_038004_COLOR_24_8_FLOAT: -- case V_038004_COLOR_10_11_11: -- case V_038004_COLOR_10_11_11_FLOAT: -- case V_038004_COLOR_11_11_10: -- case V_038004_COLOR_11_11_10_FLOAT: -- case V_038004_COLOR_2_10_10_10: -- case V_038004_COLOR_8_8_8_8: -- case V_038004_COLOR_10_10_10_2: -- case V_038004_FMT_5_9_9_9_SHAREDEXP: -- case V_038004_FMT_32_AS_8: -- case V_038004_FMT_32_AS_8_8: -- *bpe = 4; -- break; -- case V_038004_COLOR_X24_8_32_FLOAT: -- case V_038004_COLOR_32_32: -- case V_038004_COLOR_32_32_FLOAT: -- case V_038004_COLOR_16_16_16_16: -- case V_038004_COLOR_16_16_16_16_FLOAT: -- *bpe = 8; -- break; -- case V_038004_FMT_16_16_16: -- case V_038004_FMT_16_16_16_FLOAT: -- *bpe = 6; -- break; -- case V_038004_FMT_32_32_32: -- case V_038004_FMT_32_32_32_FLOAT: -- *bpe = 12; -- break; -- case V_038004_COLOR_32_32_32_32: -- case V_038004_COLOR_32_32_32_32_FLOAT: -- *bpe = 16; -- break; -- case V_038004_FMT_GB_GR: -- case V_038004_FMT_BG_RG: -- case V_038004_COLOR_INVALID: -- default: -- *bpe = 16; -- return -EINVAL; -- } -+ unsigned res; -+ -+ if (format >= ARRAY_SIZE(color_formats_table)) -+ goto fail; -+ -+ res = color_formats_table[format].blocksize; -+ if (res == 0) -+ goto fail; -+ -+ *bpe = res; - return 0; -+ -+fail: -+ *bpe = 16; -+ return -EINVAL; - } - - struct array_mode_checker { -@@ -148,7 +240,7 @@ struct array_mode_checker { - u32 nbanks; - u32 npipes; - u32 nsamples; -- u32 bpe; -+ u32 blocksize; - }; - - /* returns alignment in pixels for pitch/height/depth and bytes for base */ -@@ -162,7 +254,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value - u32 tile_height = 8; - u32 macro_tile_width = values->nbanks; - u32 macro_tile_height = values->npipes; -- u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples; -+ u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples; - u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes; - - switch (values->array_mode) { -@@ -174,7 +266,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value - *base_align = 1; - break; - case ARRAY_LINEAR_ALIGNED: -- *pitch_align = max((u32)64, (u32)(values->group_size / values->bpe)); -+ *pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize)); - *height_align = tile_height; - *depth_align = 1; - *base_align = values->group_size; -@@ -182,7 +274,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value - case ARRAY_1D_TILED_THIN1: - *pitch_align = max((u32)tile_width, - (u32)(values->group_size / -- (tile_height * values->bpe * values->nsamples))); -+ (tile_height * values->blocksize * values->nsamples))); - *height_align = tile_height; - *depth_align = 1; - *base_align = values->group_size; -@@ -190,12 +282,12 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value - case ARRAY_2D_TILED_THIN1: - *pitch_align = max((u32)macro_tile_width, - (u32)(((values->group_size / tile_height) / -- (values->bpe * values->nsamples)) * -+ (values->blocksize * values->nsamples)) * - values->nbanks)) * tile_width; - *height_align = macro_tile_height * tile_height; - *depth_align = 1; - *base_align = max(macro_tile_bytes, -- (*pitch_align) * values->bpe * (*height_align) * values->nsamples); -+ (*pitch_align) * values->blocksize * (*height_align) * values->nsamples); - break; - default: - return -EINVAL; -@@ -234,21 +326,22 @@ static void r600_cs_track_init(struct r600_cs_track *track) - static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) - { - struct r600_cs_track *track = p->track; -- u32 bpe = 0, slice_tile_max, size, tmp; -+ u32 slice_tile_max, size, tmp; - u32 height, height_align, pitch, pitch_align, depth_align; - u64 base_offset, base_align; - struct array_mode_checker array_check; - volatile u32 *ib = p->ib->ptr; - unsigned array_mode; -- -+ u32 format; - if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { - dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); - return -EINVAL; - } - size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i]; -- if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) { -+ format = G_0280A0_FORMAT(track->cb_color_info[i]); -+ if (!fmt_is_valid_color(format)) { - dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n", -- __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]), -+ __func__, __LINE__, format, - i, track->cb_color_info[i]); - return -EINVAL; - } -@@ -267,7 +360,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) - array_check.nbanks = track->nbanks; - array_check.npipes = track->npipes; - array_check.nsamples = track->nsamples; -- array_check.bpe = bpe; -+ array_check.blocksize = fmt_get_blocksize(format); - if (r600_get_array_mode_alignment(&array_check, - &pitch_align, &height_align, &depth_align, &base_align)) { - dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__, -@@ -311,7 +404,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) - } - - /* check offset */ -- tmp = height * pitch * bpe; -+ tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format); - if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { - if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { - /* the initial DDX does bad things with the CB size occasionally */ -@@ -436,7 +529,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) - array_check.nbanks = track->nbanks; - array_check.npipes = track->npipes; - array_check.nsamples = track->nsamples; -- array_check.bpe = bpe; -+ array_check.blocksize = bpe; - if (r600_get_array_mode_alignment(&array_check, - &pitch_align, &height_align, &depth_align, &base_align)) { - dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__, -@@ -1113,39 +1206,61 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx - return 0; - } - --static inline unsigned minify(unsigned size, unsigned levels) -+static inline unsigned mip_minify(unsigned size, unsigned level) - { -- size = size >> levels; -- if (size < 1) -- size = 1; -- return size; -+ unsigned val; -+ -+ val = max(1U, size >> level); -+ if (level > 0) -+ val = roundup_pow_of_two(val); -+ return val; - } - --static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels, -- unsigned w0, unsigned h0, unsigned d0, unsigned bpe, -- unsigned pitch_align, -+static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, -+ unsigned w0, unsigned h0, unsigned d0, unsigned format, -+ unsigned block_align, unsigned height_align, unsigned base_align, - unsigned *l0_size, unsigned *mipmap_size) - { -- unsigned offset, i, level, face; -- unsigned width, height, depth, rowstride, size; -- -- w0 = minify(w0, 0); -- h0 = minify(h0, 0); -- d0 = minify(d0, 0); -+ unsigned offset, i, level; -+ unsigned width, height, depth, size; -+ unsigned blocksize; -+ unsigned nbx, nby; -+ unsigned nlevels = llevel - blevel + 1; -+ -+ *l0_size = -1; -+ blocksize = fmt_get_blocksize(format); -+ -+ w0 = mip_minify(w0, 0); -+ h0 = mip_minify(h0, 0); -+ d0 = mip_minify(d0, 0); - for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) { -- width = minify(w0, i); -- height = minify(h0, i); -- depth = minify(d0, i); -- for(face = 0; face < nfaces; face++) { -- rowstride = ALIGN((width * bpe), pitch_align); -- size = height * rowstride * depth; -- offset += size; -- offset = (offset + 0x1f) & ~0x1f; -- } -+ width = mip_minify(w0, i); -+ nbx = fmt_get_nblocksx(format, width); -+ -+ nbx = round_up(nbx, block_align); -+ -+ height = mip_minify(h0, i); -+ nby = fmt_get_nblocksy(format, height); -+ nby = round_up(nby, height_align); -+ -+ depth = mip_minify(d0, i); -+ -+ size = nbx * nby * blocksize; -+ if (nfaces) -+ size *= nfaces; -+ else -+ size *= depth; -+ -+ if (i == 0) -+ *l0_size = size; -+ -+ if (i == 0 || i == 1) -+ offset = round_up(offset, base_align); -+ -+ offset += size; - } -- *l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0; - *mipmap_size = offset; -- if (!nlevels) -+ if (llevel == 0) - *mipmap_size = *l0_size; - if (!blevel) - *mipmap_size -= *l0_size; -@@ -1169,11 +1284,13 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i - u32 tiling_flags) - { - struct r600_cs_track *track = p->track; -- u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0; -- u32 word0, word1, l0_size, mipmap_size; -+ u32 nfaces, llevel, blevel, w0, h0, d0; -+ u32 word0, word1, l0_size, mipmap_size, word2, word3; - u32 height_align, pitch, pitch_align, depth_align; -+ u32 array, barray, larray; - u64 base_align; - struct array_mode_checker array_check; -+ u32 format; - - /* on legacy kernel we don't perform advanced check */ - if (p->rdev == NULL) -@@ -1199,19 +1316,25 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i - case V_038000_SQ_TEX_DIM_3D: - break; - case V_038000_SQ_TEX_DIM_CUBEMAP: -- nfaces = 6; -+ if (p->family >= CHIP_RV770) -+ nfaces = 8; -+ else -+ nfaces = 6; - break; - case V_038000_SQ_TEX_DIM_1D_ARRAY: - case V_038000_SQ_TEX_DIM_2D_ARRAY: -+ array = 1; -+ break; - case V_038000_SQ_TEX_DIM_2D_MSAA: - case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: - default: - dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0)); - return -EINVAL; - } -- if (r600_bpe_from_format(&bpe, G_038004_DATA_FORMAT(word1))) { -+ format = G_038004_DATA_FORMAT(word1); -+ if (!fmt_is_valid_texture(format)) { - dev_warn(p->dev, "%s:%d texture invalid format %d\n", -- __func__, __LINE__, G_038004_DATA_FORMAT(word1)); -+ __func__, __LINE__, format); - return -EINVAL; - } - -@@ -1222,7 +1345,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i - array_check.nbanks = track->nbanks; - array_check.npipes = track->npipes; - array_check.nsamples = 1; -- array_check.bpe = bpe; -+ array_check.blocksize = fmt_get_blocksize(format); - if (r600_get_array_mode_alignment(&array_check, - &pitch_align, &height_align, &depth_align, &base_align)) { - dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", -@@ -1248,25 +1371,34 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i - return -EINVAL; - } - -+ word2 = radeon_get_ib_value(p, idx + 2) << 8; -+ word3 = radeon_get_ib_value(p, idx + 3) << 8; -+ - word0 = radeon_get_ib_value(p, idx + 4); - word1 = radeon_get_ib_value(p, idx + 5); - blevel = G_038010_BASE_LEVEL(word0); -- nlevels = G_038014_LAST_LEVEL(word1); -- r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe, -- (pitch_align * bpe), -+ llevel = G_038014_LAST_LEVEL(word1); -+ if (array == 1) { -+ barray = G_038014_BASE_ARRAY(word1); -+ larray = G_038014_LAST_ARRAY(word1); -+ -+ nfaces = larray - barray + 1; -+ } -+ r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, -+ pitch_align, height_align, base_align, - &l0_size, &mipmap_size); - /* using get ib will give us the offset into the texture bo */ -- word0 = radeon_get_ib_value(p, idx + 2) << 8; -- if ((l0_size + word0) > radeon_bo_size(texture)) { -+ if ((l0_size + word2) > radeon_bo_size(texture)) { - dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n", -- w0, h0, bpe, word0, l0_size, radeon_bo_size(texture)); -+ w0, h0, format, word2, l0_size, radeon_bo_size(texture)); -+ dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align); - return -EINVAL; - } - /* using get ib will give us the offset into the mipmap bo */ -- word0 = radeon_get_ib_value(p, idx + 3) << 8; -- if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { -+ word3 = radeon_get_ib_value(p, idx + 3) << 8; -+ if ((mipmap_size + word3) > radeon_bo_size(mipmap)) { - /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", -- w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ -+ w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ - } - return 0; - } -@@ -1289,6 +1421,38 @@ static int r600_packet3_check(struct radeon_cs_parser *p, - idx_value = radeon_get_ib_value(p, idx); - - switch (pkt->opcode) { -+ case PACKET3_SET_PREDICATION: -+ { -+ int pred_op; -+ int tmp; -+ if (pkt->count != 1) { -+ DRM_ERROR("bad SET PREDICATION\n"); -+ return -EINVAL; -+ } -+ -+ tmp = radeon_get_ib_value(p, idx + 1); -+ pred_op = (tmp >> 16) & 0x7; -+ -+ /* for the clear predicate operation */ -+ if (pred_op == 0) -+ return 0; -+ -+ if (pred_op > 2) { -+ DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); -+ return -EINVAL; -+ } -+ -+ r = r600_cs_packet_next_reloc(p, &reloc); -+ if (r) { -+ DRM_ERROR("bad SET PREDICATION\n"); -+ return -EINVAL; -+ } -+ -+ ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); -+ ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); -+ } -+ break; -+ - case PACKET3_START_3D_CMDBUF: - if (p->family >= CHIP_RV770 || pkt->count) { - DRM_ERROR("bad START_3D\n"); -diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h -index 04bac0b..b2b944b 100644 ---- a/drivers/gpu/drm/radeon/r600d.h -+++ b/drivers/gpu/drm/radeon/r600d.h -@@ -1304,6 +1304,11 @@ - #define V_038004_FMT_16_16_16_FLOAT 0x0000002E - #define V_038004_FMT_32_32_32 0x0000002F - #define V_038004_FMT_32_32_32_FLOAT 0x00000030 -+#define V_038004_FMT_BC1 0x00000031 -+#define V_038004_FMT_BC2 0x00000032 -+#define V_038004_FMT_BC3 0x00000033 -+#define V_038004_FMT_BC4 0x00000034 -+#define V_038004_FMT_BC5 0x00000035 - #define R_038010_SQ_TEX_RESOURCE_WORD4_0 0x038010 - #define S_038010_FORMAT_COMP_X(x) (((x) & 0x3) << 0) - #define G_038010_FORMAT_COMP_X(x) (((x) >> 0) & 0x3) -diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h -index 6b34294..27df931 100644 ---- a/drivers/gpu/drm/radeon/radeon.h -+++ b/drivers/gpu/drm/radeon/radeon.h -@@ -177,7 +177,7 @@ void radeon_pm_suspend(struct radeon_device *rdev); - void radeon_pm_resume(struct radeon_device *rdev); - void radeon_combios_get_power_modes(struct radeon_device *rdev); - void radeon_atombios_get_power_modes(struct radeon_device *rdev); --void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level); -+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); - void rs690_pm_info(struct radeon_device *rdev); - extern int rv6xx_get_temp(struct radeon_device *rdev); - extern int rv770_get_temp(struct radeon_device *rdev); -@@ -651,6 +651,8 @@ struct radeon_wb { - - #define RADEON_WB_SCRATCH_OFFSET 0 - #define RADEON_WB_CP_RPTR_OFFSET 1024 -+#define RADEON_WB_CP1_RPTR_OFFSET 1280 -+#define RADEON_WB_CP2_RPTR_OFFSET 1536 - #define R600_WB_IH_WPTR_OFFSET 2048 - #define R600_WB_EVENT_OFFSET 3072 - -@@ -753,7 +755,9 @@ struct radeon_voltage { - u8 vddci_id; /* index into vddci voltage table */ - bool vddci_enabled; - /* r6xx+ sw */ -- u32 voltage; -+ u16 voltage; -+ /* evergreen+ vddci */ -+ u16 vddci; - }; - - /* clock mode flags */ -@@ -821,10 +825,12 @@ struct radeon_pm { - int default_power_state_index; - u32 current_sclk; - u32 current_mclk; -- u32 current_vddc; -+ u16 current_vddc; -+ u16 current_vddci; - u32 default_sclk; - u32 default_mclk; -- u32 default_vddc; -+ u16 default_vddc; -+ u16 default_vddci; - struct radeon_i2c_chan *i2c_bus; - /* selected pm method */ - enum radeon_pm_method pm_method; -@@ -1037,12 +1043,52 @@ struct evergreen_asic { - struct r100_gpu_lockup lockup; - }; - -+struct cayman_asic { -+ unsigned max_shader_engines; -+ unsigned max_pipes_per_simd; -+ unsigned max_tile_pipes; -+ unsigned max_simds_per_se; -+ unsigned max_backends_per_se; -+ unsigned max_texture_channel_caches; -+ unsigned max_gprs; -+ unsigned max_threads; -+ unsigned max_gs_threads; -+ unsigned max_stack_entries; -+ unsigned sx_num_of_sets; -+ unsigned sx_max_export_size; -+ unsigned sx_max_export_pos_size; -+ unsigned sx_max_export_smx_size; -+ unsigned max_hw_contexts; -+ unsigned sq_num_cf_insts; -+ unsigned sc_prim_fifo_size; -+ unsigned sc_hiz_tile_fifo_size; -+ unsigned sc_earlyz_tile_fifo_size; -+ -+ unsigned num_shader_engines; -+ unsigned num_shader_pipes_per_simd; -+ unsigned num_tile_pipes; -+ unsigned num_simds_per_se; -+ unsigned num_backends_per_se; -+ unsigned backend_disable_mask_per_asic; -+ unsigned backend_map; -+ unsigned num_texture_channel_caches; -+ unsigned mem_max_burst_length_bytes; -+ unsigned mem_row_size_in_kb; -+ unsigned shader_engine_tile_size; -+ unsigned num_gpus; -+ unsigned multi_gpu_tile_size; -+ -+ unsigned tile_config; -+ struct r100_gpu_lockup lockup; -+}; -+ - union radeon_asic_config { - struct r300_asic r300; - struct r100_asic r100; - struct r600_asic r600; - struct rv770_asic rv770; - struct evergreen_asic evergreen; -+ struct cayman_asic cayman; - }; - - /* -@@ -1133,6 +1179,9 @@ struct radeon_device { - struct radeon_mman mman; - struct radeon_fence_driver fence_drv; - struct radeon_cp cp; -+ /* cayman compute rings */ -+ struct radeon_cp cp1; -+ struct radeon_cp cp2; - struct radeon_ib_pool ib_pool; - struct radeon_irq irq; - struct radeon_asic *asic; -@@ -1504,7 +1553,7 @@ extern int evergreen_blit_init(struct radeon_device *rdev); - extern void evergreen_blit_fini(struct radeon_device *rdev); - - extern int ni_init_microcode(struct radeon_device *rdev); --extern int btc_mc_load_microcode(struct radeon_device *rdev); -+extern int ni_mc_load_microcode(struct radeon_device *rdev); - - /* radeon_acpi.c */ - #if defined(CONFIG_ACPI) -diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c -index 793c5e6..ca57619 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.c -+++ b/drivers/gpu/drm/radeon/radeon_asic.c -@@ -94,7 +94,7 @@ static void radeon_register_accessor_init(struct radeon_device *rdev) - rdev->mc_rreg = &rs600_mc_rreg; - rdev->mc_wreg = &rs600_mc_wreg; - } -- if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_HEMLOCK)) { -+ if (rdev->family >= CHIP_R600) { - rdev->pciep_rreg = &r600_pciep_rreg; - rdev->pciep_wreg = &r600_pciep_wreg; - } -@@ -885,6 +885,52 @@ static struct radeon_asic btc_asic = { - .post_page_flip = &evergreen_post_page_flip, - }; - -+static struct radeon_asic cayman_asic = { -+ .init = &cayman_init, -+ .fini = &cayman_fini, -+ .suspend = &cayman_suspend, -+ .resume = &cayman_resume, -+ .cp_commit = &r600_cp_commit, -+ .gpu_is_lockup = &cayman_gpu_is_lockup, -+ .asic_reset = &cayman_asic_reset, -+ .vga_set_state = &r600_vga_set_state, -+ .gart_tlb_flush = &cayman_pcie_gart_tlb_flush, -+ .gart_set_page = &rs600_gart_set_page, -+ .ring_test = &r600_ring_test, -+ .ring_ib_execute = &evergreen_ring_ib_execute, -+ .irq_set = &evergreen_irq_set, -+ .irq_process = &evergreen_irq_process, -+ .get_vblank_counter = &evergreen_get_vblank_counter, -+ .fence_ring_emit = &r600_fence_ring_emit, -+ .cs_parse = &evergreen_cs_parse, -+ .copy_blit = NULL, -+ .copy_dma = NULL, -+ .copy = NULL, -+ .get_engine_clock = &radeon_atom_get_engine_clock, -+ .set_engine_clock = &radeon_atom_set_engine_clock, -+ .get_memory_clock = &radeon_atom_get_memory_clock, -+ .set_memory_clock = &radeon_atom_set_memory_clock, -+ .get_pcie_lanes = NULL, -+ .set_pcie_lanes = NULL, -+ .set_clock_gating = NULL, -+ .set_surface_reg = r600_set_surface_reg, -+ .clear_surface_reg = r600_clear_surface_reg, -+ .bandwidth_update = &evergreen_bandwidth_update, -+ .hpd_init = &evergreen_hpd_init, -+ .hpd_fini = &evergreen_hpd_fini, -+ .hpd_sense = &evergreen_hpd_sense, -+ .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .gui_idle = &r600_gui_idle, -+ .pm_misc = &evergreen_pm_misc, -+ .pm_prepare = &evergreen_pm_prepare, -+ .pm_finish = &evergreen_pm_finish, -+ .pm_init_profile = &r600_pm_init_profile, -+ .pm_get_dynpm_state = &r600_pm_get_dynpm_state, -+ .pre_page_flip = &evergreen_pre_page_flip, -+ .page_flip = &evergreen_page_flip, -+ .post_page_flip = &evergreen_post_page_flip, -+}; -+ - int radeon_asic_init(struct radeon_device *rdev) - { - radeon_register_accessor_init(rdev); -@@ -977,6 +1023,9 @@ int radeon_asic_init(struct radeon_device *rdev) - case CHIP_CAICOS: - rdev->asic = &btc_asic; - break; -+ case CHIP_CAYMAN: -+ rdev->asic = &cayman_asic; -+ break; - default: - /* FIXME: not supported yet */ - return -EINVAL; -diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h -index c59bd98..82c4bc2 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.h -+++ b/drivers/gpu/drm/radeon/radeon_asic.h -@@ -375,4 +375,15 @@ extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); - extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); - extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); - -+/* -+ * cayman -+ */ -+void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev); -+int cayman_init(struct radeon_device *rdev); -+void cayman_fini(struct radeon_device *rdev); -+int cayman_suspend(struct radeon_device *rdev); -+int cayman_resume(struct radeon_device *rdev); -+bool cayman_gpu_is_lockup(struct radeon_device *rdev); -+int cayman_asic_reset(struct radeon_device *rdev); -+ - #endif -diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c -index 99768d9..f116516 100644 ---- a/drivers/gpu/drm/radeon/radeon_atombios.c -+++ b/drivers/gpu/drm/radeon/radeon_atombios.c -@@ -1599,9 +1599,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct - memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0], - fake_edid_record->ucFakeEDIDLength); - -- if (drm_edid_is_valid(edid)) -+ if (drm_edid_is_valid(edid)) { - rdev->mode_info.bios_hardcoded_edid = edid; -- else -+ rdev->mode_info.bios_hardcoded_edid_size = edid_size; -+ } else - kfree(edid); - } - } -@@ -2176,24 +2177,27 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r - } - } - --static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev) -+static void radeon_atombios_get_default_voltages(struct radeon_device *rdev, -+ u16 *vddc, u16 *vddci) - { - struct radeon_mode_info *mode_info = &rdev->mode_info; - int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); - u8 frev, crev; - u16 data_offset; - union firmware_info *firmware_info; -- u16 vddc = 0; -+ -+ *vddc = 0; -+ *vddci = 0; - - if (atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) { - firmware_info = - (union firmware_info *)(mode_info->atom_context->bios + - data_offset); -- vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); -+ *vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage); -+ if ((frev == 2) && (crev >= 2)) -+ *vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage); - } -- -- return vddc; - } - - static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, -@@ -2203,7 +2207,9 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde - int j; - u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); - u32 misc2 = le16_to_cpu(non_clock_info->usClassification); -- u16 vddc = radeon_atombios_get_default_vddc(rdev); -+ u16 vddc, vddci; -+ -+ radeon_atombios_get_default_voltages(rdev, &vddc, &vddci); - - rdev->pm.power_state[state_index].misc = misc; - rdev->pm.power_state[state_index].misc2 = misc2; -@@ -2244,6 +2250,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde - rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk; - rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk; - rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage; -+ rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci; - } else { - /* patch the table values with the default slck/mclk from firmware info */ - for (j = 0; j < mode_index; j++) { -@@ -2286,6 +2293,8 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, - VOLTAGE_SW; - rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = - le16_to_cpu(clock_info->evergreen.usVDDC); -+ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci = -+ le16_to_cpu(clock_info->evergreen.usVDDCI); - } else { - sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); - sclk |= clock_info->r600.ucEngineClockHigh << 16; -@@ -2577,25 +2586,25 @@ union set_voltage { - struct _SET_VOLTAGE_PARAMETERS_V2 v2; - }; - --void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level) -+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type) - { - union set_voltage args; - int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); -- u8 frev, crev, volt_index = level; -+ u8 frev, crev, volt_index = voltage_level; - - if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) - return; - - switch (crev) { - case 1: -- args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC; -+ args.v1.ucVoltageType = voltage_type; - args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE; - args.v1.ucVoltageIndex = volt_index; - break; - case 2: -- args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC; -+ args.v2.ucVoltageType = voltage_type; - args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE; -- args.v2.usVoltageLevel = cpu_to_le16(level); -+ args.v2.usVoltageLevel = cpu_to_le16(voltage_level); - break; - default: - DRM_ERROR("Unknown table version %d, %d\n", frev, crev); -diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c -index cf602e2..8caf546 100644 ---- a/drivers/gpu/drm/radeon/radeon_combios.c -+++ b/drivers/gpu/drm/radeon/radeon_combios.c -@@ -2079,6 +2079,19 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) - DRM_MODE_CONNECTOR_DVII, &ddc_i2c, - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, - &hpd); -+ /* TV - TV DAC */ -+ ddc_i2c.valid = false; -+ hpd.hpd = RADEON_HPD_NONE; -+ radeon_add_legacy_encoder(dev, -+ radeon_get_encoder_enum(dev, -+ ATOM_DEVICE_TV1_SUPPORT, -+ 2), -+ ATOM_DEVICE_TV1_SUPPORT); -+ radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, -+ DRM_MODE_CONNECTOR_SVIDEO, -+ &ddc_i2c, -+ CONNECTOR_OBJECT_ID_SVIDEO, -+ &hpd); - break; - default: - DRM_INFO("Connector table: %d (invalid)\n", -diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c -index d83338b..a186673 100644 ---- a/drivers/gpu/drm/radeon/radeon_connectors.c -+++ b/drivers/gpu/drm/radeon/radeon_connectors.c -@@ -998,7 +998,16 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, - (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || - (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) - return MODE_OK; -- else -+ else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) { -+ if (ASIC_IS_DCE3(rdev)) { -+ /* HDMI 1.3+ supports max clock of 340 Mhz */ -+ if (mode->clock > 340000) -+ return MODE_CLOCK_HIGH; -+ else -+ return MODE_OK; -+ } else -+ return MODE_CLOCK_HIGH; -+ } else - return MODE_CLOCK_HIGH; - } - return MODE_OK; -diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c -index 4954e2d..207d43f 100644 ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -85,6 +85,7 @@ static const char radeon_family_name[][16] = { - "BARTS", - "TURKS", - "CAICOS", -+ "CAYMAN", - "LAST", - }; - -diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c -index 275b26a..0444911 100644 ---- a/drivers/gpu/drm/radeon/radeon_drv.c -+++ b/drivers/gpu/drm/radeon/radeon_drv.c -@@ -49,9 +49,10 @@ - * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) - * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs - * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query -+ * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query - */ - #define KMS_DRIVER_MAJOR 2 --#define KMS_DRIVER_MINOR 8 -+#define KMS_DRIVER_MINOR 9 - #define KMS_DRIVER_PATCHLEVEL 0 - int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); - int radeon_driver_unload_kms(struct drm_device *dev); -diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h -index 1ca55eb..6f1d9e5 100644 ---- a/drivers/gpu/drm/radeon/radeon_family.h -+++ b/drivers/gpu/drm/radeon/radeon_family.h -@@ -84,6 +84,7 @@ enum radeon_family { - CHIP_BARTS, - CHIP_TURKS, - CHIP_CAICOS, -+ CHIP_CAYMAN, - CHIP_LAST, - }; - -diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c -index 8387d32..d36fe3f 100644 ---- a/drivers/gpu/drm/radeon/radeon_kms.c -+++ b/drivers/gpu/drm/radeon/radeon_kms.c -@@ -169,7 +169,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) - value = rdev->accel_working; - break; - case RADEON_INFO_TILING_CONFIG: -- if (rdev->family >= CHIP_CEDAR) -+ if (rdev->family >= CHIP_CAYMAN) -+ value = rdev->config.cayman.tile_config; -+ else if (rdev->family >= CHIP_CEDAR) - value = rdev->config.evergreen.tile_config; - else if (rdev->family >= CHIP_RV770) - value = rdev->config.rv770.tile_config; -@@ -205,6 +207,36 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) - /* return clock value in KHz */ - value = rdev->clock.spll.reference_freq * 10; - break; -+ case RADEON_INFO_NUM_BACKENDS: -+ if (rdev->family >= CHIP_CAYMAN) -+ value = rdev->config.cayman.max_backends_per_se * -+ rdev->config.cayman.max_shader_engines; -+ else if (rdev->family >= CHIP_CEDAR) -+ value = rdev->config.evergreen.max_backends; -+ else if (rdev->family >= CHIP_RV770) -+ value = rdev->config.rv770.max_backends; -+ else if (rdev->family >= CHIP_R600) -+ value = rdev->config.r600.max_backends; -+ else { -+ return -EINVAL; -+ } -+ break; -+ case RADEON_INFO_NUM_TILE_PIPES: -+ if (rdev->family >= CHIP_CAYMAN) -+ value = rdev->config.cayman.max_tile_pipes; -+ else if (rdev->family >= CHIP_CEDAR) -+ value = rdev->config.evergreen.max_tile_pipes; -+ else if (rdev->family >= CHIP_RV770) -+ value = rdev->config.rv770.max_tile_pipes; -+ else if (rdev->family >= CHIP_R600) -+ value = rdev->config.r600.max_tile_pipes; -+ else { -+ return -EINVAL; -+ } -+ break; -+ case RADEON_INFO_FUSION_GART_WORKING: -+ value = 1; -+ break; - default: - DRM_DEBUG_KMS("Invalid request %d\n", info->request); - return -EINVAL; -diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c -index 2aed03b..320ddc3 100644 ---- a/drivers/gpu/drm/radeon/radeon_pm.c -+++ b/drivers/gpu/drm/radeon/radeon_pm.c -@@ -23,6 +23,7 @@ - #include "drmP.h" - #include "radeon.h" - #include "avivod.h" -+#include "atom.h" - #ifdef CONFIG_ACPI - #include - #endif -@@ -533,7 +534,11 @@ void radeon_pm_resume(struct radeon_device *rdev) - /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { - if (rdev->pm.default_vddc) -- radeon_atom_set_voltage(rdev, rdev->pm.default_vddc); -+ radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, -+ SET_VOLTAGE_TYPE_ASIC_VDDC); -+ if (rdev->pm.default_vddci) -+ radeon_atom_set_voltage(rdev, rdev->pm.default_vddci, -+ SET_VOLTAGE_TYPE_ASIC_VDDCI); - if (rdev->pm.default_sclk) - radeon_set_engine_clock(rdev, rdev->pm.default_sclk); - if (rdev->pm.default_mclk) -@@ -546,6 +551,7 @@ void radeon_pm_resume(struct radeon_device *rdev) - rdev->pm.current_sclk = rdev->pm.default_sclk; - rdev->pm.current_mclk = rdev->pm.default_mclk; - rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; -+ rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci; - if (rdev->pm.pm_method == PM_METHOD_DYNPM - && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { - rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; -@@ -583,7 +589,8 @@ int radeon_pm_init(struct radeon_device *rdev) - /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { - if (rdev->pm.default_vddc) -- radeon_atom_set_voltage(rdev, rdev->pm.default_vddc); -+ radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, -+ SET_VOLTAGE_TYPE_ASIC_VDDC); - if (rdev->pm.default_sclk) - radeon_set_engine_clock(rdev, rdev->pm.default_sclk); - if (rdev->pm.default_mclk) -diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman -new file mode 100644 -index 0000000..6334f8a ---- /dev/null -+++ b/drivers/gpu/drm/radeon/reg_srcs/cayman -@@ -0,0 +1,619 @@ -+cayman 0x9400 -+0x0000802C GRBM_GFX_INDEX -+0x000088B0 VGT_VTX_VECT_EJECT_REG -+0x000088C4 VGT_CACHE_INVALIDATION -+0x000088D4 VGT_GS_VERTEX_REUSE -+0x00008958 VGT_PRIMITIVE_TYPE -+0x0000895C VGT_INDEX_TYPE -+0x00008970 VGT_NUM_INDICES -+0x00008974 VGT_NUM_INSTANCES -+0x00008990 VGT_COMPUTE_DIM_X -+0x00008994 VGT_COMPUTE_DIM_Y -+0x00008998 VGT_COMPUTE_DIM_Z -+0x0000899C VGT_COMPUTE_START_X -+0x000089A0 VGT_COMPUTE_START_Y -+0x000089A4 VGT_COMPUTE_START_Z -+0x000089A8 VGT_COMPUTE_INDEX -+0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE -+0x000089B0 VGT_HS_OFFCHIP_PARAM -+0x00008A14 PA_CL_ENHANCE -+0x00008A60 PA_SC_LINE_STIPPLE_VALUE -+0x00008B10 PA_SC_LINE_STIPPLE_STATE -+0x00008BF0 PA_SC_ENHANCE -+0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ -+0x00008D94 SQ_DYN_GPR_SIMD_LOCK_EN -+0x00008C00 SQ_CONFIG -+0x00008C04 SQ_GPR_RESOURCE_MGMT_1 -+0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1 -+0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2 -+0x00008DF8 SQ_CONST_MEM_BASE -+0x00008E20 SQ_STATIC_THREAD_MGMT_1 -+0x00008E24 SQ_STATIC_THREAD_MGMT_2 -+0x00008E28 SQ_STATIC_THREAD_MGMT_3 -+0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS -+0x00009100 SPI_CONFIG_CNTL -+0x0000913C SPI_CONFIG_CNTL_1 -+0x00009830 DB_DEBUG -+0x00009834 DB_DEBUG2 -+0x00009838 DB_DEBUG3 -+0x0000983C DB_DEBUG4 -+0x00009854 DB_WATERMARKS -+0x0000A400 TD_PS_BORDER_COLOR_INDEX -+0x0000A404 TD_PS_BORDER_COLOR_RED -+0x0000A408 TD_PS_BORDER_COLOR_GREEN -+0x0000A40C TD_PS_BORDER_COLOR_BLUE -+0x0000A410 TD_PS_BORDER_COLOR_ALPHA -+0x0000A414 TD_VS_BORDER_COLOR_INDEX -+0x0000A418 TD_VS_BORDER_COLOR_RED -+0x0000A41C TD_VS_BORDER_COLOR_GREEN -+0x0000A420 TD_VS_BORDER_COLOR_BLUE -+0x0000A424 TD_VS_BORDER_COLOR_ALPHA -+0x0000A428 TD_GS_BORDER_COLOR_INDEX -+0x0000A42C TD_GS_BORDER_COLOR_RED -+0x0000A430 TD_GS_BORDER_COLOR_GREEN -+0x0000A434 TD_GS_BORDER_COLOR_BLUE -+0x0000A438 TD_GS_BORDER_COLOR_ALPHA -+0x0000A43C TD_HS_BORDER_COLOR_INDEX -+0x0000A440 TD_HS_BORDER_COLOR_RED -+0x0000A444 TD_HS_BORDER_COLOR_GREEN -+0x0000A448 TD_HS_BORDER_COLOR_BLUE -+0x0000A44C TD_HS_BORDER_COLOR_ALPHA -+0x0000A450 TD_LS_BORDER_COLOR_INDEX -+0x0000A454 TD_LS_BORDER_COLOR_RED -+0x0000A458 TD_LS_BORDER_COLOR_GREEN -+0x0000A45C TD_LS_BORDER_COLOR_BLUE -+0x0000A460 TD_LS_BORDER_COLOR_ALPHA -+0x0000A464 TD_CS_BORDER_COLOR_INDEX -+0x0000A468 TD_CS_BORDER_COLOR_RED -+0x0000A46C TD_CS_BORDER_COLOR_GREEN -+0x0000A470 TD_CS_BORDER_COLOR_BLUE -+0x0000A474 TD_CS_BORDER_COLOR_ALPHA -+0x00028000 DB_RENDER_CONTROL -+0x00028004 DB_COUNT_CONTROL -+0x0002800C DB_RENDER_OVERRIDE -+0x00028010 DB_RENDER_OVERRIDE2 -+0x00028028 DB_STENCIL_CLEAR -+0x0002802C DB_DEPTH_CLEAR -+0x00028030 PA_SC_SCREEN_SCISSOR_TL -+0x00028034 PA_SC_SCREEN_SCISSOR_BR -+0x0002805C DB_DEPTH_SLICE -+0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0 -+0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1 -+0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2 -+0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3 -+0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4 -+0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5 -+0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6 -+0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7 -+0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8 -+0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9 -+0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10 -+0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11 -+0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12 -+0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13 -+0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14 -+0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15 -+0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0 -+0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1 -+0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2 -+0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3 -+0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4 -+0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5 -+0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6 -+0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7 -+0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8 -+0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9 -+0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10 -+0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11 -+0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12 -+0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13 -+0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14 -+0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15 -+0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0 -+0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1 -+0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2 -+0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3 -+0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4 -+0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5 -+0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6 -+0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7 -+0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8 -+0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9 -+0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10 -+0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11 -+0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12 -+0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13 -+0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14 -+0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15 -+0x00028200 PA_SC_WINDOW_OFFSET -+0x00028204 PA_SC_WINDOW_SCISSOR_TL -+0x00028208 PA_SC_WINDOW_SCISSOR_BR -+0x0002820C PA_SC_CLIPRECT_RULE -+0x00028210 PA_SC_CLIPRECT_0_TL -+0x00028214 PA_SC_CLIPRECT_0_BR -+0x00028218 PA_SC_CLIPRECT_1_TL -+0x0002821C PA_SC_CLIPRECT_1_BR -+0x00028220 PA_SC_CLIPRECT_2_TL -+0x00028224 PA_SC_CLIPRECT_2_BR -+0x00028228 PA_SC_CLIPRECT_3_TL -+0x0002822C PA_SC_CLIPRECT_3_BR -+0x00028230 PA_SC_EDGERULE -+0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET -+0x00028240 PA_SC_GENERIC_SCISSOR_TL -+0x00028244 PA_SC_GENERIC_SCISSOR_BR -+0x00028250 PA_SC_VPORT_SCISSOR_0_TL -+0x00028254 PA_SC_VPORT_SCISSOR_0_BR -+0x00028258 PA_SC_VPORT_SCISSOR_1_TL -+0x0002825C PA_SC_VPORT_SCISSOR_1_BR -+0x00028260 PA_SC_VPORT_SCISSOR_2_TL -+0x00028264 PA_SC_VPORT_SCISSOR_2_BR -+0x00028268 PA_SC_VPORT_SCISSOR_3_TL -+0x0002826C PA_SC_VPORT_SCISSOR_3_BR -+0x00028270 PA_SC_VPORT_SCISSOR_4_TL -+0x00028274 PA_SC_VPORT_SCISSOR_4_BR -+0x00028278 PA_SC_VPORT_SCISSOR_5_TL -+0x0002827C PA_SC_VPORT_SCISSOR_5_BR -+0x00028280 PA_SC_VPORT_SCISSOR_6_TL -+0x00028284 PA_SC_VPORT_SCISSOR_6_BR -+0x00028288 PA_SC_VPORT_SCISSOR_7_TL -+0x0002828C PA_SC_VPORT_SCISSOR_7_BR -+0x00028290 PA_SC_VPORT_SCISSOR_8_TL -+0x00028294 PA_SC_VPORT_SCISSOR_8_BR -+0x00028298 PA_SC_VPORT_SCISSOR_9_TL -+0x0002829C PA_SC_VPORT_SCISSOR_9_BR -+0x000282A0 PA_SC_VPORT_SCISSOR_10_TL -+0x000282A4 PA_SC_VPORT_SCISSOR_10_BR -+0x000282A8 PA_SC_VPORT_SCISSOR_11_TL -+0x000282AC PA_SC_VPORT_SCISSOR_11_BR -+0x000282B0 PA_SC_VPORT_SCISSOR_12_TL -+0x000282B4 PA_SC_VPORT_SCISSOR_12_BR -+0x000282B8 PA_SC_VPORT_SCISSOR_13_TL -+0x000282BC PA_SC_VPORT_SCISSOR_13_BR -+0x000282C0 PA_SC_VPORT_SCISSOR_14_TL -+0x000282C4 PA_SC_VPORT_SCISSOR_14_BR -+0x000282C8 PA_SC_VPORT_SCISSOR_15_TL -+0x000282CC PA_SC_VPORT_SCISSOR_15_BR -+0x000282D0 PA_SC_VPORT_ZMIN_0 -+0x000282D4 PA_SC_VPORT_ZMAX_0 -+0x000282D8 PA_SC_VPORT_ZMIN_1 -+0x000282DC PA_SC_VPORT_ZMAX_1 -+0x000282E0 PA_SC_VPORT_ZMIN_2 -+0x000282E4 PA_SC_VPORT_ZMAX_2 -+0x000282E8 PA_SC_VPORT_ZMIN_3 -+0x000282EC PA_SC_VPORT_ZMAX_3 -+0x000282F0 PA_SC_VPORT_ZMIN_4 -+0x000282F4 PA_SC_VPORT_ZMAX_4 -+0x000282F8 PA_SC_VPORT_ZMIN_5 -+0x000282FC PA_SC_VPORT_ZMAX_5 -+0x00028300 PA_SC_VPORT_ZMIN_6 -+0x00028304 PA_SC_VPORT_ZMAX_6 -+0x00028308 PA_SC_VPORT_ZMIN_7 -+0x0002830C PA_SC_VPORT_ZMAX_7 -+0x00028310 PA_SC_VPORT_ZMIN_8 -+0x00028314 PA_SC_VPORT_ZMAX_8 -+0x00028318 PA_SC_VPORT_ZMIN_9 -+0x0002831C PA_SC_VPORT_ZMAX_9 -+0x00028320 PA_SC_VPORT_ZMIN_10 -+0x00028324 PA_SC_VPORT_ZMAX_10 -+0x00028328 PA_SC_VPORT_ZMIN_11 -+0x0002832C PA_SC_VPORT_ZMAX_11 -+0x00028330 PA_SC_VPORT_ZMIN_12 -+0x00028334 PA_SC_VPORT_ZMAX_12 -+0x00028338 PA_SC_VPORT_ZMIN_13 -+0x0002833C PA_SC_VPORT_ZMAX_13 -+0x00028340 PA_SC_VPORT_ZMIN_14 -+0x00028344 PA_SC_VPORT_ZMAX_14 -+0x00028348 PA_SC_VPORT_ZMIN_15 -+0x0002834C PA_SC_VPORT_ZMAX_15 -+0x00028350 SX_MISC -+0x00028354 SX_SURFACE_SYNC -+0x00028380 SQ_VTX_SEMANTIC_0 -+0x00028384 SQ_VTX_SEMANTIC_1 -+0x00028388 SQ_VTX_SEMANTIC_2 -+0x0002838C SQ_VTX_SEMANTIC_3 -+0x00028390 SQ_VTX_SEMANTIC_4 -+0x00028394 SQ_VTX_SEMANTIC_5 -+0x00028398 SQ_VTX_SEMANTIC_6 -+0x0002839C SQ_VTX_SEMANTIC_7 -+0x000283A0 SQ_VTX_SEMANTIC_8 -+0x000283A4 SQ_VTX_SEMANTIC_9 -+0x000283A8 SQ_VTX_SEMANTIC_10 -+0x000283AC SQ_VTX_SEMANTIC_11 -+0x000283B0 SQ_VTX_SEMANTIC_12 -+0x000283B4 SQ_VTX_SEMANTIC_13 -+0x000283B8 SQ_VTX_SEMANTIC_14 -+0x000283BC SQ_VTX_SEMANTIC_15 -+0x000283C0 SQ_VTX_SEMANTIC_16 -+0x000283C4 SQ_VTX_SEMANTIC_17 -+0x000283C8 SQ_VTX_SEMANTIC_18 -+0x000283CC SQ_VTX_SEMANTIC_19 -+0x000283D0 SQ_VTX_SEMANTIC_20 -+0x000283D4 SQ_VTX_SEMANTIC_21 -+0x000283D8 SQ_VTX_SEMANTIC_22 -+0x000283DC SQ_VTX_SEMANTIC_23 -+0x000283E0 SQ_VTX_SEMANTIC_24 -+0x000283E4 SQ_VTX_SEMANTIC_25 -+0x000283E8 SQ_VTX_SEMANTIC_26 -+0x000283EC SQ_VTX_SEMANTIC_27 -+0x000283F0 SQ_VTX_SEMANTIC_28 -+0x000283F4 SQ_VTX_SEMANTIC_29 -+0x000283F8 SQ_VTX_SEMANTIC_30 -+0x000283FC SQ_VTX_SEMANTIC_31 -+0x00028400 VGT_MAX_VTX_INDX -+0x00028404 VGT_MIN_VTX_INDX -+0x00028408 VGT_INDX_OFFSET -+0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX -+0x00028410 SX_ALPHA_TEST_CONTROL -+0x00028414 CB_BLEND_RED -+0x00028418 CB_BLEND_GREEN -+0x0002841C CB_BLEND_BLUE -+0x00028420 CB_BLEND_ALPHA -+0x00028430 DB_STENCILREFMASK -+0x00028434 DB_STENCILREFMASK_BF -+0x00028438 SX_ALPHA_REF -+0x0002843C PA_CL_VPORT_XSCALE_0 -+0x00028440 PA_CL_VPORT_XOFFSET_0 -+0x00028444 PA_CL_VPORT_YSCALE_0 -+0x00028448 PA_CL_VPORT_YOFFSET_0 -+0x0002844C PA_CL_VPORT_ZSCALE_0 -+0x00028450 PA_CL_VPORT_ZOFFSET_0 -+0x00028454 PA_CL_VPORT_XSCALE_1 -+0x00028458 PA_CL_VPORT_XOFFSET_1 -+0x0002845C PA_CL_VPORT_YSCALE_1 -+0x00028460 PA_CL_VPORT_YOFFSET_1 -+0x00028464 PA_CL_VPORT_ZSCALE_1 -+0x00028468 PA_CL_VPORT_ZOFFSET_1 -+0x0002846C PA_CL_VPORT_XSCALE_2 -+0x00028470 PA_CL_VPORT_XOFFSET_2 -+0x00028474 PA_CL_VPORT_YSCALE_2 -+0x00028478 PA_CL_VPORT_YOFFSET_2 -+0x0002847C PA_CL_VPORT_ZSCALE_2 -+0x00028480 PA_CL_VPORT_ZOFFSET_2 -+0x00028484 PA_CL_VPORT_XSCALE_3 -+0x00028488 PA_CL_VPORT_XOFFSET_3 -+0x0002848C PA_CL_VPORT_YSCALE_3 -+0x00028490 PA_CL_VPORT_YOFFSET_3 -+0x00028494 PA_CL_VPORT_ZSCALE_3 -+0x00028498 PA_CL_VPORT_ZOFFSET_3 -+0x0002849C PA_CL_VPORT_XSCALE_4 -+0x000284A0 PA_CL_VPORT_XOFFSET_4 -+0x000284A4 PA_CL_VPORT_YSCALE_4 -+0x000284A8 PA_CL_VPORT_YOFFSET_4 -+0x000284AC PA_CL_VPORT_ZSCALE_4 -+0x000284B0 PA_CL_VPORT_ZOFFSET_4 -+0x000284B4 PA_CL_VPORT_XSCALE_5 -+0x000284B8 PA_CL_VPORT_XOFFSET_5 -+0x000284BC PA_CL_VPORT_YSCALE_5 -+0x000284C0 PA_CL_VPORT_YOFFSET_5 -+0x000284C4 PA_CL_VPORT_ZSCALE_5 -+0x000284C8 PA_CL_VPORT_ZOFFSET_5 -+0x000284CC PA_CL_VPORT_XSCALE_6 -+0x000284D0 PA_CL_VPORT_XOFFSET_6 -+0x000284D4 PA_CL_VPORT_YSCALE_6 -+0x000284D8 PA_CL_VPORT_YOFFSET_6 -+0x000284DC PA_CL_VPORT_ZSCALE_6 -+0x000284E0 PA_CL_VPORT_ZOFFSET_6 -+0x000284E4 PA_CL_VPORT_XSCALE_7 -+0x000284E8 PA_CL_VPORT_XOFFSET_7 -+0x000284EC PA_CL_VPORT_YSCALE_7 -+0x000284F0 PA_CL_VPORT_YOFFSET_7 -+0x000284F4 PA_CL_VPORT_ZSCALE_7 -+0x000284F8 PA_CL_VPORT_ZOFFSET_7 -+0x000284FC PA_CL_VPORT_XSCALE_8 -+0x00028500 PA_CL_VPORT_XOFFSET_8 -+0x00028504 PA_CL_VPORT_YSCALE_8 -+0x00028508 PA_CL_VPORT_YOFFSET_8 -+0x0002850C PA_CL_VPORT_ZSCALE_8 -+0x00028510 PA_CL_VPORT_ZOFFSET_8 -+0x00028514 PA_CL_VPORT_XSCALE_9 -+0x00028518 PA_CL_VPORT_XOFFSET_9 -+0x0002851C PA_CL_VPORT_YSCALE_9 -+0x00028520 PA_CL_VPORT_YOFFSET_9 -+0x00028524 PA_CL_VPORT_ZSCALE_9 -+0x00028528 PA_CL_VPORT_ZOFFSET_9 -+0x0002852C PA_CL_VPORT_XSCALE_10 -+0x00028530 PA_CL_VPORT_XOFFSET_10 -+0x00028534 PA_CL_VPORT_YSCALE_10 -+0x00028538 PA_CL_VPORT_YOFFSET_10 -+0x0002853C PA_CL_VPORT_ZSCALE_10 -+0x00028540 PA_CL_VPORT_ZOFFSET_10 -+0x00028544 PA_CL_VPORT_XSCALE_11 -+0x00028548 PA_CL_VPORT_XOFFSET_11 -+0x0002854C PA_CL_VPORT_YSCALE_11 -+0x00028550 PA_CL_VPORT_YOFFSET_11 -+0x00028554 PA_CL_VPORT_ZSCALE_11 -+0x00028558 PA_CL_VPORT_ZOFFSET_11 -+0x0002855C PA_CL_VPORT_XSCALE_12 -+0x00028560 PA_CL_VPORT_XOFFSET_12 -+0x00028564 PA_CL_VPORT_YSCALE_12 -+0x00028568 PA_CL_VPORT_YOFFSET_12 -+0x0002856C PA_CL_VPORT_ZSCALE_12 -+0x00028570 PA_CL_VPORT_ZOFFSET_12 -+0x00028574 PA_CL_VPORT_XSCALE_13 -+0x00028578 PA_CL_VPORT_XOFFSET_13 -+0x0002857C PA_CL_VPORT_YSCALE_13 -+0x00028580 PA_CL_VPORT_YOFFSET_13 -+0x00028584 PA_CL_VPORT_ZSCALE_13 -+0x00028588 PA_CL_VPORT_ZOFFSET_13 -+0x0002858C PA_CL_VPORT_XSCALE_14 -+0x00028590 PA_CL_VPORT_XOFFSET_14 -+0x00028594 PA_CL_VPORT_YSCALE_14 -+0x00028598 PA_CL_VPORT_YOFFSET_14 -+0x0002859C PA_CL_VPORT_ZSCALE_14 -+0x000285A0 PA_CL_VPORT_ZOFFSET_14 -+0x000285A4 PA_CL_VPORT_XSCALE_15 -+0x000285A8 PA_CL_VPORT_XOFFSET_15 -+0x000285AC PA_CL_VPORT_YSCALE_15 -+0x000285B0 PA_CL_VPORT_YOFFSET_15 -+0x000285B4 PA_CL_VPORT_ZSCALE_15 -+0x000285B8 PA_CL_VPORT_ZOFFSET_15 -+0x000285BC PA_CL_UCP_0_X -+0x000285C0 PA_CL_UCP_0_Y -+0x000285C4 PA_CL_UCP_0_Z -+0x000285C8 PA_CL_UCP_0_W -+0x000285CC PA_CL_UCP_1_X -+0x000285D0 PA_CL_UCP_1_Y -+0x000285D4 PA_CL_UCP_1_Z -+0x000285D8 PA_CL_UCP_1_W -+0x000285DC PA_CL_UCP_2_X -+0x000285E0 PA_CL_UCP_2_Y -+0x000285E4 PA_CL_UCP_2_Z -+0x000285E8 PA_CL_UCP_2_W -+0x000285EC PA_CL_UCP_3_X -+0x000285F0 PA_CL_UCP_3_Y -+0x000285F4 PA_CL_UCP_3_Z -+0x000285F8 PA_CL_UCP_3_W -+0x000285FC PA_CL_UCP_4_X -+0x00028600 PA_CL_UCP_4_Y -+0x00028604 PA_CL_UCP_4_Z -+0x00028608 PA_CL_UCP_4_W -+0x0002860C PA_CL_UCP_5_X -+0x00028610 PA_CL_UCP_5_Y -+0x00028614 PA_CL_UCP_5_Z -+0x00028618 PA_CL_UCP_5_W -+0x0002861C SPI_VS_OUT_ID_0 -+0x00028620 SPI_VS_OUT_ID_1 -+0x00028624 SPI_VS_OUT_ID_2 -+0x00028628 SPI_VS_OUT_ID_3 -+0x0002862C SPI_VS_OUT_ID_4 -+0x00028630 SPI_VS_OUT_ID_5 -+0x00028634 SPI_VS_OUT_ID_6 -+0x00028638 SPI_VS_OUT_ID_7 -+0x0002863C SPI_VS_OUT_ID_8 -+0x00028640 SPI_VS_OUT_ID_9 -+0x00028644 SPI_PS_INPUT_CNTL_0 -+0x00028648 SPI_PS_INPUT_CNTL_1 -+0x0002864C SPI_PS_INPUT_CNTL_2 -+0x00028650 SPI_PS_INPUT_CNTL_3 -+0x00028654 SPI_PS_INPUT_CNTL_4 -+0x00028658 SPI_PS_INPUT_CNTL_5 -+0x0002865C SPI_PS_INPUT_CNTL_6 -+0x00028660 SPI_PS_INPUT_CNTL_7 -+0x00028664 SPI_PS_INPUT_CNTL_8 -+0x00028668 SPI_PS_INPUT_CNTL_9 -+0x0002866C SPI_PS_INPUT_CNTL_10 -+0x00028670 SPI_PS_INPUT_CNTL_11 -+0x00028674 SPI_PS_INPUT_CNTL_12 -+0x00028678 SPI_PS_INPUT_CNTL_13 -+0x0002867C SPI_PS_INPUT_CNTL_14 -+0x00028680 SPI_PS_INPUT_CNTL_15 -+0x00028684 SPI_PS_INPUT_CNTL_16 -+0x00028688 SPI_PS_INPUT_CNTL_17 -+0x0002868C SPI_PS_INPUT_CNTL_18 -+0x00028690 SPI_PS_INPUT_CNTL_19 -+0x00028694 SPI_PS_INPUT_CNTL_20 -+0x00028698 SPI_PS_INPUT_CNTL_21 -+0x0002869C SPI_PS_INPUT_CNTL_22 -+0x000286A0 SPI_PS_INPUT_CNTL_23 -+0x000286A4 SPI_PS_INPUT_CNTL_24 -+0x000286A8 SPI_PS_INPUT_CNTL_25 -+0x000286AC SPI_PS_INPUT_CNTL_26 -+0x000286B0 SPI_PS_INPUT_CNTL_27 -+0x000286B4 SPI_PS_INPUT_CNTL_28 -+0x000286B8 SPI_PS_INPUT_CNTL_29 -+0x000286BC SPI_PS_INPUT_CNTL_30 -+0x000286C0 SPI_PS_INPUT_CNTL_31 -+0x000286C4 SPI_VS_OUT_CONFIG -+0x000286C8 SPI_THREAD_GROUPING -+0x000286CC SPI_PS_IN_CONTROL_0 -+0x000286D0 SPI_PS_IN_CONTROL_1 -+0x000286D4 SPI_INTERP_CONTROL_0 -+0x000286D8 SPI_INPUT_Z -+0x000286DC SPI_FOG_CNTL -+0x000286E0 SPI_BARYC_CNTL -+0x000286E4 SPI_PS_IN_CONTROL_2 -+0x000286E8 SPI_COMPUTE_INPUT_CNTL -+0x000286EC SPI_COMPUTE_NUM_THREAD_X -+0x000286F0 SPI_COMPUTE_NUM_THREAD_Y -+0x000286F4 SPI_COMPUTE_NUM_THREAD_Z -+0x000286F8 SPI_GPR_MGMT -+0x000286FC SPI_LDS_MGMT -+0x00028700 SPI_STACK_MGMT -+0x00028704 SPI_WAVE_MGMT_1 -+0x00028708 SPI_WAVE_MGMT_2 -+0x00028724 GDS_ADDR_SIZE -+0x00028780 CB_BLEND0_CONTROL -+0x00028784 CB_BLEND1_CONTROL -+0x00028788 CB_BLEND2_CONTROL -+0x0002878C CB_BLEND3_CONTROL -+0x00028790 CB_BLEND4_CONTROL -+0x00028794 CB_BLEND5_CONTROL -+0x00028798 CB_BLEND6_CONTROL -+0x0002879C CB_BLEND7_CONTROL -+0x000287CC CS_COPY_STATE -+0x000287D0 GFX_COPY_STATE -+0x000287D4 PA_CL_POINT_X_RAD -+0x000287D8 PA_CL_POINT_Y_RAD -+0x000287DC PA_CL_POINT_SIZE -+0x000287E0 PA_CL_POINT_CULL_RAD -+0x00028808 CB_COLOR_CONTROL -+0x0002880C DB_SHADER_CONTROL -+0x00028810 PA_CL_CLIP_CNTL -+0x00028814 PA_SU_SC_MODE_CNTL -+0x00028818 PA_CL_VTE_CNTL -+0x0002881C PA_CL_VS_OUT_CNTL -+0x00028820 PA_CL_NANINF_CNTL -+0x00028824 PA_SU_LINE_STIPPLE_CNTL -+0x00028828 PA_SU_LINE_STIPPLE_SCALE -+0x0002882C PA_SU_PRIM_FILTER_CNTL -+0x00028844 SQ_PGM_RESOURCES_PS -+0x00028848 SQ_PGM_RESOURCES_2_PS -+0x0002884C SQ_PGM_EXPORTS_PS -+0x00028860 SQ_PGM_RESOURCES_VS -+0x00028864 SQ_PGM_RESOURCES_2_VS -+0x00028878 SQ_PGM_RESOURCES_GS -+0x0002887C SQ_PGM_RESOURCES_2_GS -+0x00028890 SQ_PGM_RESOURCES_ES -+0x00028894 SQ_PGM_RESOURCES_2_ES -+0x000288A8 SQ_PGM_RESOURCES_FS -+0x000288BC SQ_PGM_RESOURCES_HS -+0x000288C0 SQ_PGM_RESOURCES_2_HS -+0x000288D4 SQ_PGM_RESOURCES_LS -+0x000288D8 SQ_PGM_RESOURCES_2_LS -+0x000288E8 SQ_LDS_ALLOC -+0x000288EC SQ_LDS_ALLOC_PS -+0x000288F0 SQ_VTX_SEMANTIC_CLEAR -+0x00028A00 PA_SU_POINT_SIZE -+0x00028A04 PA_SU_POINT_MINMAX -+0x00028A08 PA_SU_LINE_CNTL -+0x00028A0C PA_SC_LINE_STIPPLE -+0x00028A10 VGT_OUTPUT_PATH_CNTL -+0x00028A14 VGT_HOS_CNTL -+0x00028A18 VGT_HOS_MAX_TESS_LEVEL -+0x00028A1C VGT_HOS_MIN_TESS_LEVEL -+0x00028A20 VGT_HOS_REUSE_DEPTH -+0x00028A24 VGT_GROUP_PRIM_TYPE -+0x00028A28 VGT_GROUP_FIRST_DECR -+0x00028A2C VGT_GROUP_DECR -+0x00028A30 VGT_GROUP_VECT_0_CNTL -+0x00028A34 VGT_GROUP_VECT_1_CNTL -+0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL -+0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL -+0x00028A40 VGT_GS_MODE -+0x00028A48 PA_SC_MODE_CNTL_0 -+0x00028A4C PA_SC_MODE_CNTL_1 -+0x00028A50 VGT_ENHANCE -+0x00028A54 VGT_GS_PER_ES -+0x00028A58 VGT_ES_PER_GS -+0x00028A5C VGT_GS_PER_VS -+0x00028A6C VGT_GS_OUT_PRIM_TYPE -+0x00028A70 IA_ENHANCE -+0x00028A84 VGT_PRIMITIVEID_EN -+0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN -+0x00028AA0 VGT_INSTANCE_STEP_RATE_0 -+0x00028AA4 VGT_INSTANCE_STEP_RATE_1 -+0x00028AA8 IA_MULTI_VGT_PARAM -+0x00028AB4 VGT_REUSE_OFF -+0x00028AB8 VGT_VTX_CNT_EN -+0x00028ABC DB_HTILE_SURFACE -+0x00028AC0 DB_SRESULTS_COMPARE_STATE0 -+0x00028AC4 DB_SRESULTS_COMPARE_STATE1 -+0x00028AC8 DB_PRELOAD_CONTROL -+0x00028B38 VGT_GS_MAX_VERT_OUT -+0x00028B54 VGT_SHADER_STAGES_EN -+0x00028B58 VGT_LS_HS_CONFIG -+0x00028B6C VGT_TF_PARAM -+0x00028B70 DB_ALPHA_TO_MASK -+0x00028B74 VGT_DISPATCH_INITIATOR -+0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL -+0x00028B7C PA_SU_POLY_OFFSET_CLAMP -+0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE -+0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET -+0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE -+0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET -+0x00028B74 VGT_GS_INSTANCE_CNT -+0x00028BD4 PA_SC_CENTROID_PRIORITY_0 -+0x00028BD8 PA_SC_CENTROID_PRIORITY_1 -+0x00028BDC PA_SC_LINE_CNTL -+0x00028BE4 PA_SU_VTX_CNTL -+0x00028BE8 PA_CL_GB_VERT_CLIP_ADJ -+0x00028BEC PA_CL_GB_VERT_DISC_ADJ -+0x00028BF0 PA_CL_GB_HORZ_CLIP_ADJ -+0x00028BF4 PA_CL_GB_HORZ_DISC_ADJ -+0x00028BF8 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_0 -+0x00028BFC PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_1 -+0x00028C00 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_2 -+0x00028C04 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_3 -+0x00028C08 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_0 -+0x00028C0C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_1 -+0x00028C10 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_2 -+0x00028C14 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_3 -+0x00028C18 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_0 -+0x00028C1C PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_1 -+0x00028C20 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_2 -+0x00028C24 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_3 -+0x00028C28 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_0 -+0x00028C2C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_1 -+0x00028C30 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_2 -+0x00028C34 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_3 -+0x00028C38 PA_SC_AA_MASK_X0_Y0_X1_Y0 -+0x00028C3C PA_SC_AA_MASK_X0_Y1_X1_Y1 -+0x00028C8C CB_COLOR0_CLEAR_WORD0 -+0x00028C90 CB_COLOR0_CLEAR_WORD1 -+0x00028C94 CB_COLOR0_CLEAR_WORD2 -+0x00028C98 CB_COLOR0_CLEAR_WORD3 -+0x00028CC8 CB_COLOR1_CLEAR_WORD0 -+0x00028CCC CB_COLOR1_CLEAR_WORD1 -+0x00028CD0 CB_COLOR1_CLEAR_WORD2 -+0x00028CD4 CB_COLOR1_CLEAR_WORD3 -+0x00028D04 CB_COLOR2_CLEAR_WORD0 -+0x00028D08 CB_COLOR2_CLEAR_WORD1 -+0x00028D0C CB_COLOR2_CLEAR_WORD2 -+0x00028D10 CB_COLOR2_CLEAR_WORD3 -+0x00028D40 CB_COLOR3_CLEAR_WORD0 -+0x00028D44 CB_COLOR3_CLEAR_WORD1 -+0x00028D48 CB_COLOR3_CLEAR_WORD2 -+0x00028D4C CB_COLOR3_CLEAR_WORD3 -+0x00028D7C CB_COLOR4_CLEAR_WORD0 -+0x00028D80 CB_COLOR4_CLEAR_WORD1 -+0x00028D84 CB_COLOR4_CLEAR_WORD2 -+0x00028D88 CB_COLOR4_CLEAR_WORD3 -+0x00028DB8 CB_COLOR5_CLEAR_WORD0 -+0x00028DBC CB_COLOR5_CLEAR_WORD1 -+0x00028DC0 CB_COLOR5_CLEAR_WORD2 -+0x00028DC4 CB_COLOR5_CLEAR_WORD3 -+0x00028DF4 CB_COLOR6_CLEAR_WORD0 -+0x00028DF8 CB_COLOR6_CLEAR_WORD1 -+0x00028DFC CB_COLOR6_CLEAR_WORD2 -+0x00028E00 CB_COLOR6_CLEAR_WORD3 -+0x00028E30 CB_COLOR7_CLEAR_WORD0 -+0x00028E34 CB_COLOR7_CLEAR_WORD1 -+0x00028E38 CB_COLOR7_CLEAR_WORD2 -+0x00028E3C CB_COLOR7_CLEAR_WORD3 -+0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0 -+0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1 -+0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2 -+0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3 -+0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4 -+0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5 -+0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6 -+0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7 -+0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8 -+0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9 -+0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10 -+0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11 -+0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12 -+0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13 -+0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14 -+0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15 -+0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0 -+0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1 -+0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2 -+0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3 -+0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4 -+0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5 -+0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6 -+0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7 -+0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8 -+0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9 -+0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10 -+0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11 -+0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12 -+0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13 -+0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14 -+0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15 -+0x0003CFF0 SQ_VTX_BASE_VTX_LOC -+0x0003CFF4 SQ_VTX_START_INST_LOC -+0x0003FF00 SQ_TEX_SAMPLER_CLEAR -+0x0003FF04 SQ_TEX_RESOURCE_CLEAR -+0x0003FF08 SQ_LOOP_BOOL_CLEAR -diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen -index 9177f91..7e16371 100644 ---- a/drivers/gpu/drm/radeon/reg_srcs/evergreen -+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen -@@ -1,4 +1,5 @@ - evergreen 0x9400 -+0x0000802C GRBM_GFX_INDEX - 0x00008040 WAIT_UNTIL - 0x00008044 WAIT_UNTIL_POLL_CNTL - 0x00008048 WAIT_UNTIL_POLL_MASK -@@ -220,6 +221,7 @@ evergreen 0x9400 - 0x00028348 PA_SC_VPORT_ZMIN_15 - 0x0002834C PA_SC_VPORT_ZMAX_15 - 0x00028350 SX_MISC -+0x00028354 SX_SURFACE_SYNC - 0x00028380 SQ_VTX_SEMANTIC_0 - 0x00028384 SQ_VTX_SEMANTIC_1 - 0x00028388 SQ_VTX_SEMANTIC_2 -diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 -index af0da4a..92f1900 100644 ---- a/drivers/gpu/drm/radeon/reg_srcs/r600 -+++ b/drivers/gpu/drm/radeon/reg_srcs/r600 -@@ -708,6 +708,7 @@ r600 0x9400 - 0x00028D0C DB_RENDER_CONTROL - 0x00028D10 DB_RENDER_OVERRIDE - 0x0002880C DB_SHADER_CONTROL -+0x00028D28 DB_SRESULTS_COMPARE_STATE0 - 0x00028D2C DB_SRESULTS_COMPARE_STATE1 - 0x00028430 DB_STENCILREFMASK - 0x00028434 DB_STENCILREFMASK_BF -diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c -index 8af4679..c55cf2a 100644 ---- a/drivers/gpu/drm/radeon/rs600.c -+++ b/drivers/gpu/drm/radeon/rs600.c -@@ -48,17 +48,6 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev); - - void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) - { -- struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; -- u32 tmp; -- -- /* make sure flip is at vb rather than hb */ -- tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); -- tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; -- WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); -- -- /* set pageflip to happen anywhere in vblank interval */ -- WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); -- - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); - } -@@ -125,7 +114,7 @@ void rs600_pm_misc(struct radeon_device *rdev) - udelay(voltage->delay); - } - } else if (voltage->type == VOLTAGE_VDDC) -- radeon_atom_set_voltage(rdev, voltage->vddc_id); -+ radeon_atom_set_voltage(rdev, voltage->vddc_id, SET_VOLTAGE_TYPE_ASIC_VDDC); - - dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH); - dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf); -diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c -index 714ad45..114e5cc 100644 ---- a/drivers/gpu/drm/radeon/rv770.c -+++ b/drivers/gpu/drm/radeon/rv770.c -@@ -106,7 +106,7 @@ void rv770_pm_misc(struct radeon_device *rdev) - - if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { - if (voltage->voltage != rdev->pm.current_vddc) { -- radeon_atom_set_voltage(rdev, voltage->voltage); -+ radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); - rdev->pm.current_vddc = voltage->voltage; - DRM_DEBUG("Setting: v: %d\n", voltage->voltage); - } -diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h -index e5c607a..32c8e1c 100644 ---- a/include/drm/radeon_drm.h -+++ b/include/drm/radeon_drm.h -@@ -908,6 +908,9 @@ struct drm_radeon_cs { - #define RADEON_INFO_WANT_HYPERZ 0x07 - #define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ - #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ -+#define RADEON_INFO_NUM_BACKENDS 0x0a /* DB/backends for r600+ - need for OQ */ -+#define RADEON_INFO_NUM_TILE_PIPES 0x0b /* tile pipes for r600+ */ -+#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ - - struct drm_radeon_info { - uint32_t request; -diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h -index 6724bf3..816e30c 100644 ---- a/include/drm/drm_pciids.h -+++ b/include/drm/drm_pciids.h -@@ -141,6 +141,20 @@ - {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6703, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6704, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6705, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6706, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6707, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6708, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6709, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6718, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x6719, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x671c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ -+ {0x1002, 0x671d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6721, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6722, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \ --- -1.7.1 - diff --git a/drm-radeon-update2.patch b/drm-radeon-update2.patch deleted file mode 100644 index 1224c0fba..000000000 --- a/drm-radeon-update2.patch +++ /dev/null @@ -1,1708 +0,0 @@ -commit 05d1ee2878c955f7cf4254ed7f94bd65758f9208 -Author: Alex Deucher -Date: Wed May 25 01:00:45 2011 -0400 - - drm/radeon/kms/blit: workaround some hw issues on evergreen+ - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit e520c516656b3c361ebf8add4e00428b7c37afd6 -Author: Alex Deucher -Date: Wed May 25 16:39:00 2011 -0400 - - drm/radeon/kms: add blit support for cayman (v2) - - Allows us to use the 3D engine for memory management - and allows us to use vram beyond the BAR aperture. - - v2: fix copy paste typo - Reported-by: Nils Wallménius - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit e1b12b63f9df3a5480972c21f504163b36ceaa88 -Author: Alex Deucher -Date: Wed May 25 18:45:37 2011 -0400 - - drm/radeon/kms: fix thermal sensor reading on juniper - - Uses a different method than other evergreen asics. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 46f21922e84d074158781368eee24727a60f9d32 -Author: Alex Deucher -Date: Wed May 25 17:49:54 2011 -0400 - - drm/radeon/kms: add missing case for cayman thermal sensor - - The rest of the code is already in place. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 8cc42a1f51ada532c76009fd8b3261d5e7e8f02b -Author: Alex Deucher -Date: Fri May 20 12:35:23 2011 -0400 - - drm/radeon/kms: bump kms version number - - - proper bank size for fusion for 2D tiling. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit e0014e347d1d15e12c5beffd6af9d22a8d495969 -Author: Alex Deucher -Date: Fri May 20 12:35:22 2011 -0400 - - drm/radeon/kms: properly set num banks for fusion asics - - Needed by userspace for 2D tiled buffer alignment - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 48c7304eb2af97b6e50a93e22b656c9f3ead5f90 -Author: Alex Deucher -Date: Mon May 23 14:22:26 2011 -0400 - - drm/radeon/kms/cayman: fix typo in register mask - - Noticed by Droste on IRC. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 13e5c224cdd62fc3d454f1ef6d8157181ade07d9 -Author: Dave Airlie -Date: Thu May 19 14:14:41 2011 +1000 - - drm/radeon/kms: fix tile_config value reported to userspace on cayman. - - cayman is reporting the wrong tile config value to userspace, this - causes piglit mipmap generation tests to fail. - - Reviewed-by: Alex Deucher - cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit a9b83345a9c37d3bdea30be5a7d0cd34a0f28a68 -Author: Dave Airlie -Date: Thu May 19 14:14:40 2011 +1000 - - drm/radeon/kms: fix incorrect comparison in cayman setup code. - - This was leading to a bogus value being programmed to the backend - routing register. - - Reviewed-by: Alex Deucher - cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 4f71384abcb866214a927510d7e315ad00692faa -Author: Dave Airlie -Date: Thu May 19 14:14:43 2011 +1000 - - drm/radeon/kms: add wait idle ioctl for eg->cayman - - None of the latest GPUs had this hooked up, this is necessary for - correct operation in a lot of cases, however we should test this on a few - GPUs in these families as we've had problems in this area before. - - Reviewed-by: Alex Deucher - cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 0676d9dc1e66566af98e1192a041c9e983a69eaf -Author: Dave Airlie -Date: Thu May 19 14:14:42 2011 +1000 - - drm/radeon/cayman: setup hdp to invalidate and flush when asked - - On cayman we need to set the bit to cause HDP flushes to invalidate the - HDP cache also. - - Reviewed-by: Alex Deucher - cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 5e9df070bdc59db0b8718b8e2e6a387e49acda7c -Author: Alex Deucher -Date: Thu May 19 11:07:57 2011 -0400 - - drm/radeon/evergreen/btc/fusion: setup hdp to invalidate and flush when asked - - This needs to be explicitly set on btc. It's set by default - on evergreen/fusion, so it fine to just unconditionally enable it for - all chips. - - Signed-off-by: Alex Deucher - cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 97bce584876b2293c0ceeeb1abc33ec568d320ea -Author: Alex Deucher -Date: Thu May 12 21:15:15 2011 -0400 - - drm/radeon/kms: add some evergreen/ni safe regs - - need to programmed from the userspace drivers. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit d3be86b8137152ebf1be2ee2ccf90fea7f9a07a9 -Author: Alex Deucher -Date: Wed May 11 03:15:24 2011 -0400 - - drm/radeon/kms: fix tiling reg on fusion - - The location of MC_ARB_RAMCFG changed on fusion. - I've diffed all the other regs in evergreend.h and this - is the only other reg that changed. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 740da77e0792cd804510d018924df8f149f58fe4 -Author: Alex Deucher -Date: Tue May 10 02:14:52 2011 +0000 - - drm/radeon/kms: fix cayman acceleration - - The TCC disable setup was incorrect. This - prevents the GPU from hanging when draw commands - are issued. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 02b1b583d1c9b2559288ea5f46f04b0c8385f1ef -Author: Dave Airlie -Date: Mon May 9 14:54:33 2011 +1000 - - drm/radeon: fix cayman struct accessors. - - We are accessing totally the wrong struct in this case, and putting - uninitialised values into the GPU, which it doesn't like unsurprisingly. - - Signed-off-by: Dave Airlie - -commit 202ea65cf5d6451baf74feb4becdad19ab53eadc -Author: Ilija Hadzic -Date: Wed May 4 20:15:03 2011 -0400 - - drm/radeon: fix order of doing things in radeon_crtc_cursor_set - - if object pin or object lookup in radeon_cursor_set fail, the function - could leave inconsistent mouse width and hight values in radeon_crtc - fixed by moving cursor width and height assignments after all - checks have passed - - Signed-off-by: Ilija Hadzic - Reviewed-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit a796f1fc096d0032972480657d6d9c4fc5836496 -Author: Alex Deucher -Date: Fri May 6 01:42:49 2011 -0400 - - drm/radeon/kms: ATPX switcheroo fixes - - When we switch the display mux, also switch - the i2c mux. Also use the start and finish - methods to let the sbios know that the switch - is happening. - - Should fix: - https://bugs.freedesktop.org/show_bug.cgi?id=35398 - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 134627db513fffd8ecc90b96d477c18ae76d2d61 -Author: Alex Deucher -Date: Tue May 3 12:44:54 2011 -0400 - - drm/radeon/kms: add support for thermal chips on combios asics - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie -diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c -index e148ab0..7b4eeb7 100644 ---- a/drivers/gpu/drm/radeon/cayman_blit_shaders.c -+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c -@@ -39,17 +39,335 @@ - - const u32 cayman_default_state[] = - { -- /* XXX fill in additional blit state */ -+ 0xc0066900, -+ 0x00000000, -+ 0x00000060, /* DB_RENDER_CONTROL */ -+ 0x00000000, /* DB_COUNT_CONTROL */ -+ 0x00000000, /* DB_DEPTH_VIEW */ -+ 0x0000002a, /* DB_RENDER_OVERRIDE */ -+ 0x00000000, /* DB_RENDER_OVERRIDE2 */ -+ 0x00000000, /* DB_HTILE_DATA_BASE */ - - 0xc0026900, -- 0x00000316, -- 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ -- 0x00000010, /* */ -+ 0x0000000a, -+ 0x00000000, /* DB_STENCIL_CLEAR */ -+ 0x00000000, /* DB_DEPTH_CLEAR */ -+ -+ 0xc0036900, -+ 0x0000000f, -+ 0x00000000, /* DB_DEPTH_INFO */ -+ 0x00000000, /* DB_Z_INFO */ -+ 0x00000000, /* DB_STENCIL_INFO */ -+ -+ 0xc0016900, -+ 0x00000080, -+ 0x00000000, /* PA_SC_WINDOW_OFFSET */ -+ -+ 0xc00d6900, -+ 0x00000083, -+ 0x0000ffff, /* PA_SC_CLIPRECT_RULE */ -+ 0x00000000, /* PA_SC_CLIPRECT_0_TL */ -+ 0x20002000, /* PA_SC_CLIPRECT_0_BR */ -+ 0x00000000, -+ 0x20002000, -+ 0x00000000, -+ 0x20002000, -+ 0x00000000, -+ 0x20002000, -+ 0xaaaaaaaa, /* PA_SC_EDGERULE */ -+ 0x00000000, /* PA_SU_HARDWARE_SCREEN_OFFSET */ -+ 0x0000000f, /* CB_TARGET_MASK */ -+ 0x0000000f, /* CB_SHADER_MASK */ -+ -+ 0xc0226900, -+ 0x00000094, -+ 0x80000000, /* PA_SC_VPORT_SCISSOR_0_TL */ -+ 0x20002000, /* PA_SC_VPORT_SCISSOR_0_BR */ -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x80000000, -+ 0x20002000, -+ 0x00000000, /* PA_SC_VPORT_ZMIN_0 */ -+ 0x3f800000, /* PA_SC_VPORT_ZMAX_0 */ -+ -+ 0xc0016900, -+ 0x000000d4, -+ 0x00000000, /* SX_MISC */ - - 0xc0026900, - 0x000000d9, - 0x00000000, /* CP_RINGID */ - 0x00000000, /* CP_VMID */ -+ -+ 0xc0096900, -+ 0x00000100, -+ 0x00ffffff, /* VGT_MAX_VTX_INDX */ -+ 0x00000000, /* VGT_MIN_VTX_INDX */ -+ 0x00000000, /* VGT_INDX_OFFSET */ -+ 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_INDX */ -+ 0x00000000, /* SX_ALPHA_TEST_CONTROL */ -+ 0x00000000, /* CB_BLEND_RED */ -+ 0x00000000, /* CB_BLEND_GREEN */ -+ 0x00000000, /* CB_BLEND_BLUE */ -+ 0x00000000, /* CB_BLEND_ALPHA */ -+ -+ 0xc0016900, -+ 0x00000187, -+ 0x00000100, /* SPI_VS_OUT_ID_0 */ -+ -+ 0xc0026900, -+ 0x00000191, -+ 0x00000100, /* SPI_PS_INPUT_CNTL_0 */ -+ 0x00000101, /* SPI_PS_INPUT_CNTL_1 */ -+ -+ 0xc0016900, -+ 0x000001b1, -+ 0x00000000, /* SPI_VS_OUT_CONFIG */ -+ -+ 0xc0106900, -+ 0x000001b3, -+ 0x20000001, /* SPI_PS_IN_CONTROL_0 */ -+ 0x00000000, /* SPI_PS_IN_CONTROL_1 */ -+ 0x00000000, /* SPI_INTERP_CONTROL_0 */ -+ 0x00000000, /* SPI_INPUT_Z */ -+ 0x00000000, /* SPI_FOG_CNTL */ -+ 0x00100000, /* SPI_BARYC_CNTL */ -+ 0x00000000, /* SPI_PS_IN_CONTROL_2 */ -+ 0x00000000, /* SPI_COMPUTE_INPUT_CNTL */ -+ 0x00000000, /* SPI_COMPUTE_NUM_THREAD_X */ -+ 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Y */ -+ 0x00000000, /* SPI_COMPUTE_NUM_THREAD_Z */ -+ 0x00000000, /* SPI_GPR_MGMT */ -+ 0x00000000, /* SPI_LDS_MGMT */ -+ 0x00000000, /* SPI_STACK_MGMT */ -+ 0x00000000, /* SPI_WAVE_MGMT_1 */ -+ 0x00000000, /* SPI_WAVE_MGMT_2 */ -+ -+ 0xc0016900, -+ 0x000001e0, -+ 0x00000000, /* CB_BLEND0_CONTROL */ -+ -+ 0xc00e6900, -+ 0x00000200, -+ 0x00000000, /* DB_DEPTH_CONTROL */ -+ 0x00000000, /* DB_EQAA */ -+ 0x00cc0010, /* CB_COLOR_CONTROL */ -+ 0x00000210, /* DB_SHADER_CONTROL */ -+ 0x00010000, /* PA_CL_CLIP_CNTL */ -+ 0x00000004, /* PA_SU_SC_MODE_CNTL */ -+ 0x00000100, /* PA_CL_VTE_CNTL */ -+ 0x00000000, /* PA_CL_VS_OUT_CNTL */ -+ 0x00000000, /* PA_CL_NANINF_CNTL */ -+ 0x00000000, /* PA_SU_LINE_STIPPLE_CNTL */ -+ 0x00000000, /* PA_SU_LINE_STIPPLE_SCALE */ -+ 0x00000000, /* PA_SU_PRIM_FILTER_CNTL */ -+ 0x00000000, /* */ -+ 0x00000000, /* */ -+ -+ 0xc0026900, -+ 0x00000229, -+ 0x00000000, /* SQ_PGM_START_FS */ -+ 0x00000000, -+ -+ 0xc0016900, -+ 0x0000023b, -+ 0x00000000, /* SQ_LDS_ALLOC_PS */ -+ -+ 0xc0066900, -+ 0x00000240, -+ 0x00000000, /* SQ_ESGS_RING_ITEMSIZE */ -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ -+ 0xc0046900, -+ 0x00000247, -+ 0x00000000, /* SQ_GS_VERT_ITEMSIZE */ -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ -+ 0xc0116900, -+ 0x00000280, -+ 0x00000000, /* PA_SU_POINT_SIZE */ -+ 0x00000000, /* PA_SU_POINT_MINMAX */ -+ 0x00000008, /* PA_SU_LINE_CNTL */ -+ 0x00000000, /* PA_SC_LINE_STIPPLE */ -+ 0x00000000, /* VGT_OUTPUT_PATH_CNTL */ -+ 0x00000000, /* VGT_HOS_CNTL */ -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, /* VGT_GS_MODE */ -+ -+ 0xc0026900, -+ 0x00000292, -+ 0x00000000, /* PA_SC_MODE_CNTL_0 */ -+ 0x00000000, /* PA_SC_MODE_CNTL_1 */ -+ -+ 0xc0016900, -+ 0x000002a1, -+ 0x00000000, /* VGT_PRIMITIVEID_EN */ -+ -+ 0xc0016900, -+ 0x000002a5, -+ 0x00000000, /* VGT_MULTI_PRIM_IB_RESET_EN */ -+ -+ 0xc0026900, -+ 0x000002a8, -+ 0x00000000, /* VGT_INSTANCE_STEP_RATE_0 */ -+ 0x00000000, -+ -+ 0xc0026900, -+ 0x000002ad, -+ 0x00000000, /* VGT_REUSE_OFF */ -+ 0x00000000, -+ -+ 0xc0016900, -+ 0x000002d5, -+ 0x00000000, /* VGT_SHADER_STAGES_EN */ -+ -+ 0xc0016900, -+ 0x000002dc, -+ 0x0000aa00, /* DB_ALPHA_TO_MASK */ -+ -+ 0xc0066900, -+ 0x000002de, -+ 0x00000000, /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ -+ 0xc0026900, -+ 0x000002e5, -+ 0x00000000, /* VGT_STRMOUT_CONFIG */ -+ 0x00000000, -+ -+ 0xc01b6900, -+ 0x000002f5, -+ 0x76543210, /* PA_SC_CENTROID_PRIORITY_0 */ -+ 0xfedcba98, /* PA_SC_CENTROID_PRIORITY_1 */ -+ 0x00000000, /* PA_SC_LINE_CNTL */ -+ 0x00000000, /* PA_SC_AA_CONFIG */ -+ 0x00000005, /* PA_SU_VTX_CNTL */ -+ 0x3f800000, /* PA_CL_GB_VERT_CLIP_ADJ */ -+ 0x3f800000, /* PA_CL_GB_VERT_DISC_ADJ */ -+ 0x3f800000, /* PA_CL_GB_HORZ_CLIP_ADJ */ -+ 0x3f800000, /* PA_CL_GB_HORZ_DISC_ADJ */ -+ 0x00000000, /* PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 */ -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0xffffffff, /* PA_SC_AA_MASK_X0Y0_X1Y0 */ -+ 0xffffffff, -+ -+ 0xc0026900, -+ 0x00000316, -+ 0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */ -+ 0x00000010, /* */ -+}; -+ -+const u32 cayman_vs[] = -+{ -+ 0x00000004, -+ 0x80400400, -+ 0x0000a03c, -+ 0x95000688, -+ 0x00004000, -+ 0x15000688, -+ 0x00000000, -+ 0x88000000, -+ 0x04000000, -+ 0x67961001, -+#ifdef __BIG_ENDIAN -+ 0x00020000, -+#else -+ 0x00000000, -+#endif -+ 0x00000000, -+ 0x04000000, -+ 0x67961000, -+#ifdef __BIG_ENDIAN -+ 0x00020008, -+#else -+ 0x00000008, -+#endif -+ 0x00000000, -+}; -+ -+const u32 cayman_ps[] = -+{ -+ 0x00000004, -+ 0xa00c0000, -+ 0x00000008, -+ 0x80400000, -+ 0x00000000, -+ 0x95000688, -+ 0x00000000, -+ 0x88000000, -+ 0x00380400, -+ 0x00146b10, -+ 0x00380000, -+ 0x20146b10, -+ 0x00380400, -+ 0x40146b00, -+ 0x80380000, -+ 0x60146b00, -+ 0x00000010, -+ 0x000d1000, -+ 0xb0800000, -+ 0x00000000, - }; - -+const u32 cayman_ps_size = ARRAY_SIZE(cayman_ps); -+const u32 cayman_vs_size = ARRAY_SIZE(cayman_vs); - const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state); -diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.h b/drivers/gpu/drm/radeon/cayman_blit_shaders.h -index 33b75e5..f5d0e9a 100644 ---- a/drivers/gpu/drm/radeon/cayman_blit_shaders.h -+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.h -@@ -25,8 +25,11 @@ - #ifndef CAYMAN_BLIT_SHADERS_H - #define CAYMAN_BLIT_SHADERS_H - -+extern const u32 cayman_ps[]; -+extern const u32 cayman_vs[]; - extern const u32 cayman_default_state[]; - -+extern const u32 cayman_ps_size, cayman_vs_size; - extern const u32 cayman_default_size; - - #endif -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index f7e0376..1b583f8 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -88,21 +88,39 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) - /* get temperature in millidegrees */ - int evergreen_get_temp(struct radeon_device *rdev) - { -- u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> -- ASIC_T_SHIFT; -- u32 actual_temp = 0; -- -- if (temp & 0x400) -- actual_temp = -256; -- else if (temp & 0x200) -- actual_temp = 255; -- else if (temp & 0x100) { -- actual_temp = temp & 0x1ff; -- actual_temp |= ~0x1ff; -- } else -- actual_temp = temp & 0xff; -+ u32 temp, toffset, actual_temp = 0; -+ -+ if (rdev->family == CHIP_JUNIPER) { -+ toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> -+ TOFFSET_SHIFT; -+ temp = (RREG32(CG_TS0_STATUS) & TS0_ADC_DOUT_MASK) >> -+ TS0_ADC_DOUT_SHIFT; -+ -+ if (toffset & 0x100) -+ actual_temp = temp / 2 - (0x200 - toffset); -+ else -+ actual_temp = temp / 2 + toffset; -+ -+ actual_temp = actual_temp * 1000; -+ -+ } else { -+ temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >> -+ ASIC_T_SHIFT; -+ -+ if (temp & 0x400) -+ actual_temp = -256; -+ else if (temp & 0x200) -+ actual_temp = 255; -+ else if (temp & 0x100) { -+ actual_temp = temp & 0x1ff; -+ actual_temp |= ~0x1ff; -+ } else -+ actual_temp = temp & 0xff; - -- return (actual_temp * 1000) / 2; -+ actual_temp = (actual_temp * 1000) / 2; -+ } -+ -+ return actual_temp; - } - - int sumo_get_temp(struct radeon_device *rdev) -@@ -1578,7 +1596,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) - u32 sq_stack_resource_mgmt_2; - u32 sq_stack_resource_mgmt_3; - u32 vgt_cache_invalidation; -- u32 hdp_host_path_cntl; -+ u32 hdp_host_path_cntl, tmp; - int i, j, num_shader_engines, ps_thread_count; - - switch (rdev->family) { -@@ -1780,7 +1798,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev) - - - mc_shared_chmap = RREG32(MC_SHARED_CHMAP); -- mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); -+ if (rdev->flags & RADEON_IS_IGP) -+ mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG); -+ else -+ mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); - - switch (rdev->config.evergreen.max_tile_pipes) { - case 1: -@@ -1933,8 +1954,12 @@ static void evergreen_gpu_init(struct radeon_device *rdev) - rdev->config.evergreen.tile_config |= (3 << 0); - break; - } -- rdev->config.evergreen.tile_config |= -- ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; -+ /* num banks is 8 on all fusion asics */ -+ if (rdev->flags & RADEON_IS_IGP) -+ rdev->config.evergreen.tile_config |= 8 << 4; -+ else -+ rdev->config.evergreen.tile_config |= -+ ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; - rdev->config.evergreen.tile_config |= - ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; - rdev->config.evergreen.tile_config |= -@@ -2138,6 +2163,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev) - for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) - WREG32(i, 0); - -+ tmp = RREG32(HDP_MISC_CNTL); -+ tmp |= HDP_FLUSH_INVALIDATE_CACHE; -+ WREG32(HDP_MISC_CNTL, tmp); -+ - hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); - WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); - -diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c -index 2be698e..9c91468 100644 ---- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c -+++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c -@@ -31,6 +31,7 @@ - - #include "evergreend.h" - #include "evergreen_blit_shaders.h" -+#include "cayman_blit_shaders.h" - - #define DI_PT_RECTLIST 0x11 - #define DI_INDEX_SIZE_16_BIT 0x0 -@@ -199,6 +200,16 @@ static void - set_scissors(struct radeon_device *rdev, int x1, int y1, - int x2, int y2) - { -+ /* workaround some hw bugs */ -+ if (x2 == 0) -+ x1 = 1; -+ if (y2 == 0) -+ y1 = 1; -+ if (rdev->family == CHIP_CAYMAN) { -+ if ((x2 == 1) && (y2 == 1)) -+ x2 = 2; -+ } -+ - radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); - radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_START) >> 2); - radeon_ring_write(rdev, (x1 << 0) | (y1 << 16)); -@@ -255,238 +266,240 @@ set_default_state(struct radeon_device *rdev) - u64 gpu_addr; - int dwords; - -- switch (rdev->family) { -- case CHIP_CEDAR: -- default: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 96; -- num_vs_threads = 16; -- num_gs_threads = 16; -- num_es_threads = 16; -- num_hs_threads = 16; -- num_ls_threads = 16; -- num_ps_stack_entries = 42; -- num_vs_stack_entries = 42; -- num_gs_stack_entries = 42; -- num_es_stack_entries = 42; -- num_hs_stack_entries = 42; -- num_ls_stack_entries = 42; -- break; -- case CHIP_REDWOOD: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 128; -- num_vs_threads = 20; -- num_gs_threads = 20; -- num_es_threads = 20; -- num_hs_threads = 20; -- num_ls_threads = 20; -- num_ps_stack_entries = 42; -- num_vs_stack_entries = 42; -- num_gs_stack_entries = 42; -- num_es_stack_entries = 42; -- num_hs_stack_entries = 42; -- num_ls_stack_entries = 42; -- break; -- case CHIP_JUNIPER: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 128; -- num_vs_threads = 20; -- num_gs_threads = 20; -- num_es_threads = 20; -- num_hs_threads = 20; -- num_ls_threads = 20; -- num_ps_stack_entries = 85; -- num_vs_stack_entries = 85; -- num_gs_stack_entries = 85; -- num_es_stack_entries = 85; -- num_hs_stack_entries = 85; -- num_ls_stack_entries = 85; -- break; -- case CHIP_CYPRESS: -- case CHIP_HEMLOCK: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 128; -- num_vs_threads = 20; -- num_gs_threads = 20; -- num_es_threads = 20; -- num_hs_threads = 20; -- num_ls_threads = 20; -- num_ps_stack_entries = 85; -- num_vs_stack_entries = 85; -- num_gs_stack_entries = 85; -- num_es_stack_entries = 85; -- num_hs_stack_entries = 85; -- num_ls_stack_entries = 85; -- break; -- case CHIP_PALM: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 96; -- num_vs_threads = 16; -- num_gs_threads = 16; -- num_es_threads = 16; -- num_hs_threads = 16; -- num_ls_threads = 16; -- num_ps_stack_entries = 42; -- num_vs_stack_entries = 42; -- num_gs_stack_entries = 42; -- num_es_stack_entries = 42; -- num_hs_stack_entries = 42; -- num_ls_stack_entries = 42; -- break; -- case CHIP_BARTS: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 128; -- num_vs_threads = 20; -- num_gs_threads = 20; -- num_es_threads = 20; -- num_hs_threads = 20; -- num_ls_threads = 20; -- num_ps_stack_entries = 85; -- num_vs_stack_entries = 85; -- num_gs_stack_entries = 85; -- num_es_stack_entries = 85; -- num_hs_stack_entries = 85; -- num_ls_stack_entries = 85; -- break; -- case CHIP_TURKS: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 128; -- num_vs_threads = 20; -- num_gs_threads = 20; -- num_es_threads = 20; -- num_hs_threads = 20; -- num_ls_threads = 20; -- num_ps_stack_entries = 42; -- num_vs_stack_entries = 42; -- num_gs_stack_entries = 42; -- num_es_stack_entries = 42; -- num_hs_stack_entries = 42; -- num_ls_stack_entries = 42; -- break; -- case CHIP_CAICOS: -- num_ps_gprs = 93; -- num_vs_gprs = 46; -- num_temp_gprs = 4; -- num_gs_gprs = 31; -- num_es_gprs = 31; -- num_hs_gprs = 23; -- num_ls_gprs = 23; -- num_ps_threads = 128; -- num_vs_threads = 10; -- num_gs_threads = 10; -- num_es_threads = 10; -- num_hs_threads = 10; -- num_ls_threads = 10; -- num_ps_stack_entries = 42; -- num_vs_stack_entries = 42; -- num_gs_stack_entries = 42; -- num_es_stack_entries = 42; -- num_hs_stack_entries = 42; -- num_ls_stack_entries = 42; -- break; -- } -- -- if ((rdev->family == CHIP_CEDAR) || -- (rdev->family == CHIP_PALM) || -- (rdev->family == CHIP_CAICOS)) -- sq_config = 0; -- else -- sq_config = VC_ENABLE; -- -- sq_config |= (EXPORT_SRC_C | -- CS_PRIO(0) | -- LS_PRIO(0) | -- HS_PRIO(0) | -- PS_PRIO(0) | -- VS_PRIO(1) | -- GS_PRIO(2) | -- ES_PRIO(3)); -- -- sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | -- NUM_VS_GPRS(num_vs_gprs) | -- NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); -- sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | -- NUM_ES_GPRS(num_es_gprs)); -- sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | -- NUM_LS_GPRS(num_ls_gprs)); -- sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | -- NUM_VS_THREADS(num_vs_threads) | -- NUM_GS_THREADS(num_gs_threads) | -- NUM_ES_THREADS(num_es_threads)); -- sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | -- NUM_LS_THREADS(num_ls_threads)); -- sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | -- NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); -- sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | -- NUM_ES_STACK_ENTRIES(num_es_stack_entries)); -- sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | -- NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); -- - /* set clear context state */ - radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0)); - radeon_ring_write(rdev, 0); - -- /* disable dyn gprs */ -- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); -- radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); -- radeon_ring_write(rdev, 0); -+ if (rdev->family < CHIP_CAYMAN) { -+ switch (rdev->family) { -+ case CHIP_CEDAR: -+ default: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 96; -+ num_vs_threads = 16; -+ num_gs_threads = 16; -+ num_es_threads = 16; -+ num_hs_threads = 16; -+ num_ls_threads = 16; -+ num_ps_stack_entries = 42; -+ num_vs_stack_entries = 42; -+ num_gs_stack_entries = 42; -+ num_es_stack_entries = 42; -+ num_hs_stack_entries = 42; -+ num_ls_stack_entries = 42; -+ break; -+ case CHIP_REDWOOD: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 128; -+ num_vs_threads = 20; -+ num_gs_threads = 20; -+ num_es_threads = 20; -+ num_hs_threads = 20; -+ num_ls_threads = 20; -+ num_ps_stack_entries = 42; -+ num_vs_stack_entries = 42; -+ num_gs_stack_entries = 42; -+ num_es_stack_entries = 42; -+ num_hs_stack_entries = 42; -+ num_ls_stack_entries = 42; -+ break; -+ case CHIP_JUNIPER: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 128; -+ num_vs_threads = 20; -+ num_gs_threads = 20; -+ num_es_threads = 20; -+ num_hs_threads = 20; -+ num_ls_threads = 20; -+ num_ps_stack_entries = 85; -+ num_vs_stack_entries = 85; -+ num_gs_stack_entries = 85; -+ num_es_stack_entries = 85; -+ num_hs_stack_entries = 85; -+ num_ls_stack_entries = 85; -+ break; -+ case CHIP_CYPRESS: -+ case CHIP_HEMLOCK: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 128; -+ num_vs_threads = 20; -+ num_gs_threads = 20; -+ num_es_threads = 20; -+ num_hs_threads = 20; -+ num_ls_threads = 20; -+ num_ps_stack_entries = 85; -+ num_vs_stack_entries = 85; -+ num_gs_stack_entries = 85; -+ num_es_stack_entries = 85; -+ num_hs_stack_entries = 85; -+ num_ls_stack_entries = 85; -+ break; -+ case CHIP_PALM: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 96; -+ num_vs_threads = 16; -+ num_gs_threads = 16; -+ num_es_threads = 16; -+ num_hs_threads = 16; -+ num_ls_threads = 16; -+ num_ps_stack_entries = 42; -+ num_vs_stack_entries = 42; -+ num_gs_stack_entries = 42; -+ num_es_stack_entries = 42; -+ num_hs_stack_entries = 42; -+ num_ls_stack_entries = 42; -+ break; -+ case CHIP_BARTS: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 128; -+ num_vs_threads = 20; -+ num_gs_threads = 20; -+ num_es_threads = 20; -+ num_hs_threads = 20; -+ num_ls_threads = 20; -+ num_ps_stack_entries = 85; -+ num_vs_stack_entries = 85; -+ num_gs_stack_entries = 85; -+ num_es_stack_entries = 85; -+ num_hs_stack_entries = 85; -+ num_ls_stack_entries = 85; -+ break; -+ case CHIP_TURKS: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 128; -+ num_vs_threads = 20; -+ num_gs_threads = 20; -+ num_es_threads = 20; -+ num_hs_threads = 20; -+ num_ls_threads = 20; -+ num_ps_stack_entries = 42; -+ num_vs_stack_entries = 42; -+ num_gs_stack_entries = 42; -+ num_es_stack_entries = 42; -+ num_hs_stack_entries = 42; -+ num_ls_stack_entries = 42; -+ break; -+ case CHIP_CAICOS: -+ num_ps_gprs = 93; -+ num_vs_gprs = 46; -+ num_temp_gprs = 4; -+ num_gs_gprs = 31; -+ num_es_gprs = 31; -+ num_hs_gprs = 23; -+ num_ls_gprs = 23; -+ num_ps_threads = 128; -+ num_vs_threads = 10; -+ num_gs_threads = 10; -+ num_es_threads = 10; -+ num_hs_threads = 10; -+ num_ls_threads = 10; -+ num_ps_stack_entries = 42; -+ num_vs_stack_entries = 42; -+ num_gs_stack_entries = 42; -+ num_es_stack_entries = 42; -+ num_hs_stack_entries = 42; -+ num_ls_stack_entries = 42; -+ break; -+ } - -- /* SQ config */ -- radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); -- radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); -- radeon_ring_write(rdev, sq_config); -- radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); -- radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); -- radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); -- radeon_ring_write(rdev, 0); -- radeon_ring_write(rdev, 0); -- radeon_ring_write(rdev, sq_thread_resource_mgmt); -- radeon_ring_write(rdev, sq_thread_resource_mgmt_2); -- radeon_ring_write(rdev, sq_stack_resource_mgmt_1); -- radeon_ring_write(rdev, sq_stack_resource_mgmt_2); -- radeon_ring_write(rdev, sq_stack_resource_mgmt_3); -+ if ((rdev->family == CHIP_CEDAR) || -+ (rdev->family == CHIP_PALM) || -+ (rdev->family == CHIP_CAICOS)) -+ sq_config = 0; -+ else -+ sq_config = VC_ENABLE; -+ -+ sq_config |= (EXPORT_SRC_C | -+ CS_PRIO(0) | -+ LS_PRIO(0) | -+ HS_PRIO(0) | -+ PS_PRIO(0) | -+ VS_PRIO(1) | -+ GS_PRIO(2) | -+ ES_PRIO(3)); -+ -+ sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) | -+ NUM_VS_GPRS(num_vs_gprs) | -+ NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); -+ sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) | -+ NUM_ES_GPRS(num_es_gprs)); -+ sq_gpr_resource_mgmt_3 = (NUM_HS_GPRS(num_hs_gprs) | -+ NUM_LS_GPRS(num_ls_gprs)); -+ sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) | -+ NUM_VS_THREADS(num_vs_threads) | -+ NUM_GS_THREADS(num_gs_threads) | -+ NUM_ES_THREADS(num_es_threads)); -+ sq_thread_resource_mgmt_2 = (NUM_HS_THREADS(num_hs_threads) | -+ NUM_LS_THREADS(num_ls_threads)); -+ sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | -+ NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); -+ sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | -+ NUM_ES_STACK_ENTRIES(num_es_stack_entries)); -+ sq_stack_resource_mgmt_3 = (NUM_HS_STACK_ENTRIES(num_hs_stack_entries) | -+ NUM_LS_STACK_ENTRIES(num_ls_stack_entries)); -+ -+ /* disable dyn gprs */ -+ radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); -+ radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2); -+ radeon_ring_write(rdev, 0); -+ -+ /* SQ config */ -+ radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11)); -+ radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); -+ radeon_ring_write(rdev, sq_config); -+ radeon_ring_write(rdev, sq_gpr_resource_mgmt_1); -+ radeon_ring_write(rdev, sq_gpr_resource_mgmt_2); -+ radeon_ring_write(rdev, sq_gpr_resource_mgmt_3); -+ radeon_ring_write(rdev, 0); -+ radeon_ring_write(rdev, 0); -+ radeon_ring_write(rdev, sq_thread_resource_mgmt); -+ radeon_ring_write(rdev, sq_thread_resource_mgmt_2); -+ radeon_ring_write(rdev, sq_stack_resource_mgmt_1); -+ radeon_ring_write(rdev, sq_stack_resource_mgmt_2); -+ radeon_ring_write(rdev, sq_stack_resource_mgmt_3); -+ } - - /* CONTEXT_CONTROL */ - radeon_ring_write(rdev, 0xc0012800); -@@ -560,7 +573,10 @@ int evergreen_blit_init(struct radeon_device *rdev) - mutex_init(&rdev->r600_blit.mutex); - rdev->r600_blit.state_offset = 0; - -- rdev->r600_blit.state_len = evergreen_default_size; -+ if (rdev->family < CHIP_CAYMAN) -+ rdev->r600_blit.state_len = evergreen_default_size; -+ else -+ rdev->r600_blit.state_len = cayman_default_size; - - dwords = rdev->r600_blit.state_len; - while (dwords & 0xf) { -@@ -572,11 +588,17 @@ int evergreen_blit_init(struct radeon_device *rdev) - obj_size = ALIGN(obj_size, 256); - - rdev->r600_blit.vs_offset = obj_size; -- obj_size += evergreen_vs_size * 4; -+ if (rdev->family < CHIP_CAYMAN) -+ obj_size += evergreen_vs_size * 4; -+ else -+ obj_size += cayman_vs_size * 4; - obj_size = ALIGN(obj_size, 256); - - rdev->r600_blit.ps_offset = obj_size; -- obj_size += evergreen_ps_size * 4; -+ if (rdev->family < CHIP_CAYMAN) -+ obj_size += evergreen_ps_size * 4; -+ else -+ obj_size += cayman_ps_size * 4; - obj_size = ALIGN(obj_size, 256); - - r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, -@@ -599,16 +621,29 @@ int evergreen_blit_init(struct radeon_device *rdev) - return r; - } - -- memcpy_toio(ptr + rdev->r600_blit.state_offset, -- evergreen_default_state, rdev->r600_blit.state_len * 4); -- -- if (num_packet2s) -- memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), -- packet2s, num_packet2s * 4); -- for (i = 0; i < evergreen_vs_size; i++) -- *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]); -- for (i = 0; i < evergreen_ps_size; i++) -- *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]); -+ if (rdev->family < CHIP_CAYMAN) { -+ memcpy_toio(ptr + rdev->r600_blit.state_offset, -+ evergreen_default_state, rdev->r600_blit.state_len * 4); -+ -+ if (num_packet2s) -+ memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), -+ packet2s, num_packet2s * 4); -+ for (i = 0; i < evergreen_vs_size; i++) -+ *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(evergreen_vs[i]); -+ for (i = 0; i < evergreen_ps_size; i++) -+ *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(evergreen_ps[i]); -+ } else { -+ memcpy_toio(ptr + rdev->r600_blit.state_offset, -+ cayman_default_state, rdev->r600_blit.state_len * 4); -+ -+ if (num_packet2s) -+ memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), -+ packet2s, num_packet2s * 4); -+ for (i = 0; i < cayman_vs_size; i++) -+ *(u32 *)((unsigned long)ptr + rdev->r600_blit.vs_offset + i * 4) = cpu_to_le32(cayman_vs[i]); -+ for (i = 0; i < cayman_ps_size; i++) -+ *(u32 *)((unsigned long)ptr + rdev->r600_blit.ps_offset + i * 4) = cpu_to_le32(cayman_ps[i]); -+ } - radeon_bo_kunmap(rdev->r600_blit.shader_obj); - radeon_bo_unreserve(rdev->r600_blit.shader_obj); - -diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h -index 9453384..1636e34 100644 ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -64,6 +64,8 @@ - #define GB_BACKEND_MAP 0x98FC - #define DMIF_ADDR_CONFIG 0xBD4 - #define HDP_ADDR_CONFIG 0x2F48 -+#define HDP_MISC_CNTL 0x2F4C -+#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) - - #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 - #define GC_USER_RB_BACKEND_DISABLE 0x9B7C -@@ -166,10 +168,16 @@ - #define SE_DB_BUSY (1 << 30) - #define SE_CB_BUSY (1 << 31) - /* evergreen */ -+#define CG_THERMAL_CTRL 0x72c -+#define TOFFSET_MASK 0x00003FE0 -+#define TOFFSET_SHIFT 5 - #define CG_MULT_THERMAL_STATUS 0x740 - #define ASIC_T(x) ((x) << 16) --#define ASIC_T_MASK 0x7FF0000 -+#define ASIC_T_MASK 0x07FF0000 - #define ASIC_T_SHIFT 16 -+#define CG_TS0_STATUS 0x760 -+#define TS0_ADC_DOUT_MASK 0x000003FF -+#define TS0_ADC_DOUT_SHIFT 0 - /* APU */ - #define CG_THERMAL_STATUS 0x678 - -@@ -200,6 +208,7 @@ - #define BURSTLENGTH_SHIFT 9 - #define BURSTLENGTH_MASK 0x00000200 - #define CHANSIZE_OVERRIDE (1 << 11) -+#define FUS_MC_ARB_RAMCFG 0x2768 - #define MC_VM_AGP_TOP 0x2028 - #define MC_VM_AGP_BOT 0x202C - #define MC_VM_AGP_BASE 0x2030 -diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c -index 8c199c4..b226cca 100644 ---- a/drivers/gpu/drm/radeon/ni.c -+++ b/drivers/gpu/drm/radeon/ni.c -@@ -417,7 +417,7 @@ static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev, - num_shader_engines = 1; - if (num_shader_engines > rdev->config.cayman.max_shader_engines) - num_shader_engines = rdev->config.cayman.max_shader_engines; -- if (num_backends_per_asic > num_shader_engines) -+ if (num_backends_per_asic < num_shader_engines) - num_backends_per_asic = num_shader_engines; - if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines)) - num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines; -@@ -674,7 +674,7 @@ static void cayman_gpu_init(struct radeon_device *rdev) - - cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); - cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); -- cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE); -+ cgts_tcc_disable = 0xff000000; - gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); - gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG); - cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); -@@ -829,7 +829,7 @@ static void cayman_gpu_init(struct radeon_device *rdev) - rdev->config.cayman.tile_config |= - ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; - rdev->config.cayman.tile_config |= -- (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; -+ ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; - rdev->config.cayman.tile_config |= - ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; - -@@ -871,7 +871,7 @@ static void cayman_gpu_init(struct radeon_device *rdev) - - smx_dc_ctl0 = RREG32(SMX_DC_CTL0); - smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff); -- smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); -+ smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets); - WREG32(SMX_DC_CTL0, smx_dc_ctl0); - - WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE); -@@ -887,20 +887,20 @@ static void cayman_gpu_init(struct radeon_device *rdev) - - WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO); - -- WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | -- POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | -- SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); -+ WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) | -+ POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) | -+ SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1))); - -- WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) | -- SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) | -- SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size))); -+ WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) | -+ SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) | -+ SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size))); - - - WREG32(VGT_NUM_INSTANCES, 1); - - WREG32(CP_PERFMON_CNTL, 0); - -- WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) | -+ WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) | - FETCH_FIFO_HIWATER(0x4) | - DONE_FIFO_HIWATER(0xe0) | - ALU_UPDATE_FIFO_HIWATER(0x8))); -@@ -931,6 +931,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) - WREG32(CB_PERF_CTR3_SEL_0, 0); - WREG32(CB_PERF_CTR3_SEL_1, 0); - -+ tmp = RREG32(HDP_MISC_CNTL); -+ tmp |= HDP_FLUSH_INVALIDATE_CACHE; -+ WREG32(HDP_MISC_CNTL, tmp); -+ - hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); - WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); - -@@ -1383,14 +1387,12 @@ static int cayman_startup(struct radeon_device *rdev) - return r; - cayman_gpu_init(rdev); - --#if 0 -- r = cayman_blit_init(rdev); -+ r = evergreen_blit_init(rdev); - if (r) { -- cayman_blit_fini(rdev); -+ evergreen_blit_fini(rdev); - rdev->asic->copy = NULL; - dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); - } --#endif - - /* allocate wb buffer */ - r = radeon_wb_init(rdev); -@@ -1448,7 +1450,7 @@ int cayman_resume(struct radeon_device *rdev) - - int cayman_suspend(struct radeon_device *rdev) - { -- /* int r; */ -+ int r; - - /* FIXME: we should wait for ring to be empty */ - cayman_cp_enable(rdev, false); -@@ -1457,14 +1459,13 @@ int cayman_suspend(struct radeon_device *rdev) - radeon_wb_disable(rdev); - cayman_pcie_gart_disable(rdev); - --#if 0 - /* unpin shaders bo */ - r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); - if (likely(r == 0)) { - radeon_bo_unpin(rdev->r600_blit.shader_obj); - radeon_bo_unreserve(rdev->r600_blit.shader_obj); - } --#endif -+ - return 0; - } - -@@ -1576,7 +1577,7 @@ int cayman_init(struct radeon_device *rdev) - - void cayman_fini(struct radeon_device *rdev) - { -- /* cayman_blit_fini(rdev); */ -+ evergreen_blit_fini(rdev); - cayman_cp_fini(rdev); - r600_irq_fini(rdev); - radeon_wb_fini(rdev); -diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h -index 0f9a08b..9736746 100644 ---- a/drivers/gpu/drm/radeon/nid.h -+++ b/drivers/gpu/drm/radeon/nid.h -@@ -136,6 +136,8 @@ - #define HDP_NONSURFACE_INFO 0x2C08 - #define HDP_NONSURFACE_SIZE 0x2C0C - #define HDP_ADDR_CONFIG 0x2F48 -+#define HDP_MISC_CNTL 0x2F4C -+#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) - - #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 - #define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C -@@ -351,7 +353,7 @@ - #define MULTI_GPU_TILE_SIZE_MASK 0x03000000 - #define MULTI_GPU_TILE_SIZE_SHIFT 24 - #define ROW_SIZE(x) ((x) << 28) --#define ROW_SIZE_MASK 0x30000007 -+#define ROW_SIZE_MASK 0x30000000 - #define ROW_SIZE_SHIFT 28 - #define NUM_LOWER_PIPES(x) ((x) << 30) - #define NUM_LOWER_PIPES_MASK 0x40000000 -diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c -index ca57619..b9b3c2a 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.c -+++ b/drivers/gpu/drm/radeon/radeon_asic.c -@@ -782,6 +782,7 @@ static struct radeon_asic evergreen_asic = { - .hpd_fini = &evergreen_hpd_fini, - .hpd_sense = &evergreen_hpd_sense, - .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, - .gui_idle = &r600_gui_idle, - .pm_misc = &evergreen_pm_misc, - .pm_prepare = &evergreen_pm_prepare, -@@ -828,6 +829,7 @@ static struct radeon_asic sumo_asic = { - .hpd_fini = &evergreen_hpd_fini, - .hpd_sense = &evergreen_hpd_sense, - .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, - .gui_idle = &r600_gui_idle, - .pm_misc = &evergreen_pm_misc, - .pm_prepare = &evergreen_pm_prepare, -@@ -874,6 +876,7 @@ static struct radeon_asic btc_asic = { - .hpd_fini = &evergreen_hpd_fini, - .hpd_sense = &evergreen_hpd_sense, - .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, - .gui_idle = &r600_gui_idle, - .pm_misc = &evergreen_pm_misc, - .pm_prepare = &evergreen_pm_prepare, -@@ -903,9 +906,9 @@ static struct radeon_asic cayman_asic = { - .get_vblank_counter = &evergreen_get_vblank_counter, - .fence_ring_emit = &r600_fence_ring_emit, - .cs_parse = &evergreen_cs_parse, -- .copy_blit = NULL, -- .copy_dma = NULL, -- .copy = NULL, -+ .copy_blit = &evergreen_copy_blit, -+ .copy_dma = &evergreen_copy_blit, -+ .copy = &evergreen_copy_blit, - .get_engine_clock = &radeon_atom_get_engine_clock, - .set_engine_clock = &radeon_atom_set_engine_clock, - .get_memory_clock = &radeon_atom_get_memory_clock, -@@ -920,6 +923,7 @@ static struct radeon_asic cayman_asic = { - .hpd_fini = &evergreen_hpd_fini, - .hpd_sense = &evergreen_hpd_sense, - .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, - .gui_idle = &r600_gui_idle, - .pm_misc = &evergreen_pm_misc, - .pm_prepare = &evergreen_pm_prepare, -diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c -index ed5dfe5..9d95792 100644 ---- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c -+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c -@@ -15,6 +15,9 @@ - #define ATPX_VERSION 0 - #define ATPX_GPU_PWR 2 - #define ATPX_MUX_SELECT 3 -+#define ATPX_I2C_MUX_SELECT 4 -+#define ATPX_SWITCH_START 5 -+#define ATPX_SWITCH_END 6 - - #define ATPX_INTEGRATED 0 - #define ATPX_DISCRETE 1 -@@ -149,13 +152,35 @@ static int radeon_atpx_switch_mux(acpi_handle handle, int mux_id) - return radeon_atpx_execute(handle, ATPX_MUX_SELECT, mux_id); - } - -+static int radeon_atpx_switch_i2c_mux(acpi_handle handle, int mux_id) -+{ -+ return radeon_atpx_execute(handle, ATPX_I2C_MUX_SELECT, mux_id); -+} -+ -+static int radeon_atpx_switch_start(acpi_handle handle, int gpu_id) -+{ -+ return radeon_atpx_execute(handle, ATPX_SWITCH_START, gpu_id); -+} -+ -+static int radeon_atpx_switch_end(acpi_handle handle, int gpu_id) -+{ -+ return radeon_atpx_execute(handle, ATPX_SWITCH_END, gpu_id); -+} - - static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) - { -+ int gpu_id; -+ - if (id == VGA_SWITCHEROO_IGD) -- radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 0); -+ gpu_id = ATPX_INTEGRATED; - else -- radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 1); -+ gpu_id = ATPX_DISCRETE; -+ -+ radeon_atpx_switch_start(radeon_atpx_priv.atpx_handle, gpu_id); -+ radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, gpu_id); -+ radeon_atpx_switch_i2c_mux(radeon_atpx_priv.atpx_handle, gpu_id); -+ radeon_atpx_switch_end(radeon_atpx_priv.atpx_handle, gpu_id); -+ - return 0; - } - -diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c -index 8caf546..089ab92 100644 ---- a/drivers/gpu/drm/radeon/radeon_combios.c -+++ b/drivers/gpu/drm/radeon/radeon_combios.c -@@ -2504,6 +2504,12 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) - return true; - } - -+static const char *thermal_controller_names[] = { -+ "NONE", -+ "lm63", -+ "adm1032", -+}; -+ - void radeon_combios_get_power_modes(struct radeon_device *rdev) - { - struct drm_device *dev = rdev->ddev; -@@ -2524,6 +2530,54 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) - return; - } - -+ /* check for a thermal chip */ -+ offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE); -+ if (offset) { -+ u8 thermal_controller = 0, gpio = 0, i2c_addr = 0, clk_bit = 0, data_bit = 0; -+ struct radeon_i2c_bus_rec i2c_bus; -+ -+ rev = RBIOS8(offset); -+ -+ if (rev == 0) { -+ thermal_controller = RBIOS8(offset + 3); -+ gpio = RBIOS8(offset + 4) & 0x3f; -+ i2c_addr = RBIOS8(offset + 5); -+ } else if (rev == 1) { -+ thermal_controller = RBIOS8(offset + 4); -+ gpio = RBIOS8(offset + 5) & 0x3f; -+ i2c_addr = RBIOS8(offset + 6); -+ } else if (rev == 2) { -+ thermal_controller = RBIOS8(offset + 4); -+ gpio = RBIOS8(offset + 5) & 0x3f; -+ i2c_addr = RBIOS8(offset + 6); -+ clk_bit = RBIOS8(offset + 0xa); -+ data_bit = RBIOS8(offset + 0xb); -+ } -+ if ((thermal_controller > 0) && (thermal_controller < 3)) { -+ DRM_INFO("Possible %s thermal controller at 0x%02x\n", -+ thermal_controller_names[thermal_controller], -+ i2c_addr >> 1); -+ if (gpio == DDC_LCD) { -+ /* MM i2c */ -+ i2c_bus.valid = true; -+ i2c_bus.hw_capable = true; -+ i2c_bus.mm_i2c = true; -+ i2c_bus.i2c_id = 0xa0; -+ } else if (gpio == DDC_GPIO) -+ i2c_bus = combios_setup_i2c_bus(rdev, gpio, 1 << clk_bit, 1 << data_bit); -+ else -+ i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0); -+ rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); -+ if (rdev->pm.i2c_bus) { -+ struct i2c_board_info info = { }; -+ const char *name = thermal_controller_names[thermal_controller]; -+ info.addr = i2c_addr >> 1; -+ strlcpy(info.type, name, sizeof(info.type)); -+ i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); -+ } -+ } -+ } -+ - if (rdev->flags & RADEON_IS_MOBILITY) { - offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); - if (offset) { -diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c -index 017ac54..5df2acd 100644 ---- a/drivers/gpu/drm/radeon/radeon_cursor.c -+++ b/drivers/gpu/drm/radeon/radeon_cursor.c -@@ -167,9 +167,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, - return -EINVAL; - } - -- radeon_crtc->cursor_width = width; -- radeon_crtc->cursor_height = height; -- - obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); - if (!obj) { - DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); -@@ -180,6 +177,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, - if (ret) - goto fail; - -+ radeon_crtc->cursor_width = width; -+ radeon_crtc->cursor_height = height; -+ - radeon_lock_cursor(crtc, true); - /* XXX only 27 bit offset for legacy cursor */ - radeon_set_cursor(crtc, obj, gpu_addr); -diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c -index 0444911..fc44376 100644 ---- a/drivers/gpu/drm/radeon/radeon_drv.c -+++ b/drivers/gpu/drm/radeon/radeon_drv.c -@@ -50,9 +50,10 @@ - * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs - * 2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query - * 2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query -+ * 2.10.0 - fusion 2D tiling - */ - #define KMS_DRIVER_MAJOR 2 --#define KMS_DRIVER_MINOR 9 -+#define KMS_DRIVER_MINOR 10 - #define KMS_DRIVER_PATCHLEVEL 0 - int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); - int radeon_driver_unload_kms(struct drm_device *dev); -diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c -index 320ddc3..4fec348 100644 ---- a/drivers/gpu/drm/radeon/radeon_pm.c -+++ b/drivers/gpu/drm/radeon/radeon_pm.c -@@ -485,6 +485,7 @@ static int radeon_hwmon_init(struct radeon_device *rdev) - case THERMAL_TYPE_RV6XX: - case THERMAL_TYPE_RV770: - case THERMAL_TYPE_EVERGREEN: -+ case THERMAL_TYPE_NI: - case THERMAL_TYPE_SUMO: - rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); - if (IS_ERR(rdev->pm.int_hwmon_dev)) { -diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman -index 6334f8a..0aa8e85 100644 ---- a/drivers/gpu/drm/radeon/reg_srcs/cayman -+++ b/drivers/gpu/drm/radeon/reg_srcs/cayman -@@ -33,6 +33,7 @@ cayman 0x9400 - 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS - 0x00009100 SPI_CONFIG_CNTL - 0x0000913C SPI_CONFIG_CNTL_1 -+0x00009508 TA_CNTL_AUX - 0x00009830 DB_DEBUG - 0x00009834 DB_DEBUG2 - 0x00009838 DB_DEBUG3 -diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen -index 7e16371..0e28cae 100644 ---- a/drivers/gpu/drm/radeon/reg_srcs/evergreen -+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen -@@ -46,6 +46,7 @@ evergreen 0x9400 - 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS - 0x00009100 SPI_CONFIG_CNTL - 0x0000913C SPI_CONFIG_CNTL_1 -+0x00009508 TA_CNTL_AUX - 0x00009700 VC_CNTL - 0x00009714 VC_ENHANCE - 0x00009830 DB_DEBUG diff --git a/drm-radeon-update3.patch b/drm-radeon-update3.patch deleted file mode 100644 index 626ccdc4b..000000000 --- a/drm-radeon-update3.patch +++ /dev/null @@ -1,820 +0,0 @@ -commit 3c79cf677a2eca93762d15f69744937d43185573 -Author: Alex Deucher -Date: Thu Jun 23 12:19:32 2011 -0400 - - drm/radeon/kms: handle special cases for vddc - - A voltage value of 0xff01 requires that the driver - look up the max voltage for the board based using the - atom SetVoltage command table. - - Setting the proper voltage should fix stability on - some newer asics. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 63311583922e52b7687233c18e9eebe83207d2e8 -Author: Alex Deucher -Date: Thu Jun 23 00:49:29 2011 -0400 - - drm/radeon/kms: fix num_banks tiling config for fusion - - The field is encoded: - 0 = 4 banks - 1 = 8 banks - 2 = 16 banks - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 1421991c155016ce31777d09ebfdfe3eb04cb78c -Author: Alex Deucher -Date: Mon Jun 20 13:00:31 2011 -0400 - - drm/radeon/kms/r6xx+: voltage fixes - - 0xff01 is not an actual voltage value, but a flag - for the driver. If the power state as that value, - skip setting the voltage. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit a7b65dda144af8ba443f1745875440c87a41b0a3 -Author: Dave Airlie -Date: Sat Jun 18 03:59:51 2011 +0000 - - drm/radeon: avoid warnings from r600/eg irq handlers on powered off card. - - Since we were calling the wptr function before checking if the IH was - even enabled, or the GPU wasn't shutdown, we'd get spam in the logs when - the GPU readback 0xffffffff. This reorders things so we return early - in the no IH and GPU shutdown cases. - - Reported-and-tested-by: ManDay on #radeon - Reviewed-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 3f662051e0acf55bc8c2ea246c9f05e004a2d698 -Author: Alex Deucher -Date: Fri Jun 17 06:11:30 2011 +0000 - - drm/radeon/kms: add missing param for dce3.2 DP transmitter setup - - This is used during phy init to set up the phy for DP. This may - fix DP problems on DCE3.2 cards. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit dc4f34ba0796f4b09501b035825c02c405335063 -Author: Alex Deucher -Date: Fri Jun 17 13:13:52 2011 -0400 - - drm/radeon/kms/atom: fix duallink on some early DCE3.2 cards - - Certain revisions of the vbios on DCE3.2 cards have a bug - in the transmitter control table which prevents duallink from - being enabled properly on some cards. The action switch statement - jumps to the wrong offset for the OUTPUT_ENABLE action. The fix - is to use the ENABLE action rather than the OUTPUT_ENABLE action - on the affected cards. In fixed version of the vbios, both - actions jump to the same offset, so the change should be safe. - - Reported-and-tested-by: Dave Airlie - Signed-off-by: Alex Deucher - Cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit b5097472f2119480f60657f92b17dd79bcf8e24a -Author: Alex Deucher -Date: Mon Jun 13 17:39:06 2011 -0400 - - drm/radeon/kms: use helper functions for fence read/write - - The existing code assumed scratch registers in a number - of places while in most cases we are be using writeback - and events rather than scratch registers. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 4414ac4ea84407d14e9fde512c1c229f9cfc96c4 -Author: Alex Deucher -Date: Thu Jun 16 18:14:22 2011 +0000 - - drm/radeon/kms: fix num crtcs for Cedar and Caicos - - Only support 4 rather than 6. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit c4eee24a87a71c14f223e85065cccea6bf32321d -Author: Alex Deucher -Date: Mon Jun 13 22:02:51 2011 +0000 - - drm/radeon/kms: clear wb memory by default - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit 12ca85df2db5988ea5c53d0ee53ff1b1cf1257fd -Author: Alex Deucher -Date: Tue Jun 14 19:15:53 2011 +0000 - - drm/radeon/kms: signed fix for evergreen thermal - - temperature is signed. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit dd53acd144d8fa6385e50949f4f635890420ba0b -Author: Alex Deucher -Date: Wed Jun 8 13:01:11 2011 -0400 - - drm/radeon/kms: check modes against max pixel clock - - Filter out modes that are higher than the max pixel - clock. - - Signed-off-by: Alex Deucher - Signed-off-by: Dave Airlie - -commit a812b560d0d041f2318ae4243ead692e26bae429 -Author: Daniel Haid -Date: Wed Jun 8 20:04:45 2011 +1000 - - drm/radeon/kms: fix for radeon on systems >4GB without hardware iommu - - On my x86_64 system with >4GB of ram and swiotlb instead of - a hardware iommu (because I have a VIA chipset), the call - to pci_set_dma_mask (see below) with 40bits returns an error. - - But it seems that the radeon driver is designed to have - need_dma32 = true exactly if pci_set_dma_mask is called - with 32 bits and false if it is called with 40 bits. - - I have read somewhere that the default are 32 bits. So if the - call fails I suppose that need_dma32 should be set to true. - - And indeed the patch fixes the problem I have had before - and which I had described here: - http://choon.net/forum/read.php?21,106131,115940 - - Acked-by: Alex Deucher - cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 262016fe924bbc06d50bcfc816c635d465cd503d -Author: Alex Deucher -Date: Fri May 27 10:05:03 2011 -0400 - - drm/radeon/kms: viewport height has to be even - - Otherwise, no vblank interrupts. - Fixes: - https://bugs.freedesktop.org/show_bug.cgi?id=37522 - - Signed-off-by: Alex Deucher - Cc: stable@kernel.org - Signed-off-by: Dave Airlie - -commit 36b3cb168810e68ae8dd2036189c4f2cfc0c6d49 -Author: Marek Olšák -Date: Fri Jun 10 14:41:26 2011 +0000 - - drm/radeon/kms: do bounds checking for 3D_LOAD_VBPNTR and bump array limit - - To my knowledge, the limit is 16 on r300. - (the docs don't say what the limit is) - - The lack of bounds checking can be abused to do all sorts of things - (from bypassing parts of the CS checker to crashing the kernel). - - Bugzilla: - https://bugs.freedesktop.org/show_bug.cgi?id=36745 - - Cc: stable@kernel.org - Signed-off-by: Marek Olšák - Signed-off-by: Dave Airlie -diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c -index 2bab32f..1fce6b7 100644 ---- a/drivers/gpu/drm/radeon/atombios_crtc.c -+++ b/drivers/gpu/drm/radeon/atombios_crtc.c -@@ -1011,7 +1011,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, - uint64_t fb_location; - uint32_t fb_format, fb_pitch_pixels, tiling_flags; - u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); -- u32 tmp; -+ u32 tmp, viewport_w, viewport_h; - int r; - - /* no fb bound */ -@@ -1137,8 +1137,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, - y &= ~1; - WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, - (x << 16) | y); -+ viewport_w = crtc->mode.hdisplay; -+ viewport_h = (crtc->mode.vdisplay + 1) & ~1; - WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, -- (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); -+ (viewport_w << 16) | viewport_h); - - /* pageflip setup */ - /* make sure flip is at vb rather than hb */ -@@ -1179,7 +1181,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, - uint64_t fb_location; - uint32_t fb_format, fb_pitch_pixels, tiling_flags; - u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; -- u32 tmp; -+ u32 tmp, viewport_w, viewport_h; - int r; - - /* no fb bound */ -@@ -1304,8 +1306,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, - y &= ~1; - WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, - (x << 16) | y); -+ viewport_w = crtc->mode.hdisplay; -+ viewport_h = (crtc->mode.vdisplay + 1) & ~1; - WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, -- (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); -+ (viewport_w << 16) | viewport_h); - - /* pageflip setup */ - /* make sure flip is at vb rather than hb */ -diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c -index 1b583f8..81f5211 100644 ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) - /* get temperature in millidegrees */ - int evergreen_get_temp(struct radeon_device *rdev) - { -- u32 temp, toffset, actual_temp = 0; -+ u32 temp, toffset; -+ int actual_temp = 0; - - if (rdev->family == CHIP_JUNIPER) { - toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> -@@ -139,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev) - struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; - - if (voltage->type == VOLTAGE_SW) { -+ /* 0xff01 is a flag rather then an actual voltage */ -+ if (voltage->voltage == 0xff01) -+ return; - if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { - radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); - rdev->pm.current_vddc = voltage->voltage; - DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); - } -+ /* 0xff01 is a flag rather then an actual voltage */ -+ if (voltage->vddci == 0xff01) -+ return; - if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { - radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); - rdev->pm.current_vddci = voltage->vddci; -@@ -1954,9 +1961,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev) - rdev->config.evergreen.tile_config |= (3 << 0); - break; - } -- /* num banks is 8 on all fusion asics */ -+ /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ - if (rdev->flags & RADEON_IS_IGP) -- rdev->config.evergreen.tile_config |= 8 << 4; -+ rdev->config.evergreen.tile_config |= 1 << 4; - else - rdev->config.evergreen.tile_config |= - ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; -@@ -2636,28 +2643,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) - - int evergreen_irq_process(struct radeon_device *rdev) - { -- u32 wptr = evergreen_get_ih_wptr(rdev); -- u32 rptr = rdev->ih.rptr; -+ u32 wptr; -+ u32 rptr; - u32 src_id, src_data; - u32 ring_index; - unsigned long flags; - bool queue_hotplug = false; - -- DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); -- if (!rdev->ih.enabled) -+ if (!rdev->ih.enabled || rdev->shutdown) - return IRQ_NONE; - -- spin_lock_irqsave(&rdev->ih.lock, flags); -+ wptr = evergreen_get_ih_wptr(rdev); -+ rptr = rdev->ih.rptr; -+ DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); - -+ spin_lock_irqsave(&rdev->ih.lock, flags); - if (rptr == wptr) { - spin_unlock_irqrestore(&rdev->ih.lock, flags); - return IRQ_NONE; - } -- if (rdev->shutdown) { -- spin_unlock_irqrestore(&rdev->ih.lock, flags); -- return IRQ_NONE; -- } -- - restart_ih: - /* display interrupts */ - evergreen_irq_ack(rdev); -diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h -index 2fef9de..686f9dc 100644 ---- a/drivers/gpu/drm/radeon/r100_track.h -+++ b/drivers/gpu/drm/radeon/r100_track.h -@@ -63,7 +63,7 @@ struct r100_cs_track { - unsigned num_arrays; - unsigned max_indx; - unsigned color_channel_mask; -- struct r100_cs_track_array arrays[11]; -+ struct r100_cs_track_array arrays[16]; - struct r100_cs_track_cb cb[R300_MAX_CB]; - struct r100_cs_track_cb zb; - struct r100_cs_track_cb aa; -@@ -146,6 +146,12 @@ static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p, - ib = p->ib->ptr; - track = (struct r100_cs_track *)p->track; - c = radeon_get_ib_value(p, idx++) & 0x1F; -+ if (c > 16) { -+ DRM_ERROR("Only 16 vertex buffers are allowed %d\n", -+ pkt->opcode); -+ r100_cs_dump_packet(p, pkt); -+ return -EINVAL; -+ } - track->num_arrays = c; - for (i = 0; i < (c - 1); i+=2, idx+=3) { - r = r100_cs_packet_next_reloc(p, &reloc); -diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c -index 70e9fb0..e7157b7 100644 ---- a/drivers/gpu/drm/radeon/r600.c -+++ b/drivers/gpu/drm/radeon/r600.c -@@ -586,6 +586,9 @@ void r600_pm_misc(struct radeon_device *rdev) - struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; - - if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { -+ /* 0xff01 is a flag rather then an actual voltage */ -+ if (voltage->voltage == 0xff01) -+ return; - if (voltage->voltage != rdev->pm.current_vddc) { - radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); - rdev->pm.current_vddc = voltage->voltage; -@@ -3286,27 +3289,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) - - int r600_irq_process(struct radeon_device *rdev) - { -- u32 wptr = r600_get_ih_wptr(rdev); -- u32 rptr = rdev->ih.rptr; -+ u32 wptr; -+ u32 rptr; - u32 src_id, src_data; - u32 ring_index; - unsigned long flags; - bool queue_hotplug = false; - -- DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); -- if (!rdev->ih.enabled) -+ if (!rdev->ih.enabled || rdev->shutdown) - return IRQ_NONE; - -+ wptr = r600_get_ih_wptr(rdev); -+ rptr = rdev->ih.rptr; -+ DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); -+ - spin_lock_irqsave(&rdev->ih.lock, flags); - - if (rptr == wptr) { - spin_unlock_irqrestore(&rdev->ih.lock, flags); - return IRQ_NONE; - } -- if (rdev->shutdown) { -- spin_unlock_irqrestore(&rdev->ih.lock, flags); -- return IRQ_NONE; -- } - - restart_ih: - /* display interrupts */ -diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h -index 27df931..c46552d 100644 ---- a/drivers/gpu/drm/radeon/radeon.h -+++ b/drivers/gpu/drm/radeon/radeon.h -@@ -165,6 +165,7 @@ struct radeon_clock { - uint32_t default_sclk; - uint32_t default_dispclk; - uint32_t dp_extclk; -+ uint32_t max_pixel_clock; - }; - - /* -@@ -178,6 +179,7 @@ void radeon_pm_resume(struct radeon_device *rdev); - void radeon_combios_get_power_modes(struct radeon_device *rdev); - void radeon_atombios_get_power_modes(struct radeon_device *rdev); - void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); -+int radeon_atom_get_max_vddc(struct radeon_device *rdev, u16 *voltage); - void rs690_pm_info(struct radeon_device *rdev); - extern int rv6xx_get_temp(struct radeon_device *rdev); - extern int rv770_get_temp(struct radeon_device *rdev); -diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c -index b9b3c2a..6f5bd29 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.c -+++ b/drivers/gpu/drm/radeon/radeon_asic.c -@@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = { - int radeon_asic_init(struct radeon_device *rdev) - { - radeon_register_accessor_init(rdev); -+ -+ /* set the number of crtcs */ -+ if (rdev->flags & RADEON_SINGLE_CRTC) -+ rdev->num_crtc = 1; -+ else -+ rdev->num_crtc = 2; -+ - switch (rdev->family) { - case CHIP_R100: - case CHIP_RV100: -@@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev) - case CHIP_JUNIPER: - case CHIP_CYPRESS: - case CHIP_HEMLOCK: -+ /* set num crtcs */ -+ if (rdev->family == CHIP_CEDAR) -+ rdev->num_crtc = 4; -+ else -+ rdev->num_crtc = 6; - rdev->asic = &evergreen_asic; - break; - case CHIP_PALM: -@@ -1025,10 +1037,17 @@ int radeon_asic_init(struct radeon_device *rdev) - case CHIP_BARTS: - case CHIP_TURKS: - case CHIP_CAICOS: -+ /* set num crtcs */ -+ if (rdev->family == CHIP_CAICOS) -+ rdev->num_crtc = 4; -+ else -+ rdev->num_crtc = 6; - rdev->asic = &btc_asic; - break; - case CHIP_CAYMAN: - rdev->asic = &cayman_asic; -+ /* set num crtcs */ -+ rdev->num_crtc = 6; - break; - default: - /* FIXME: not supported yet */ -@@ -1040,18 +1059,6 @@ int radeon_asic_init(struct radeon_device *rdev) - rdev->asic->set_memory_clock = NULL; - } - -- /* set the number of crtcs */ -- if (rdev->flags & RADEON_SINGLE_CRTC) -- rdev->num_crtc = 1; -- else { -- if (ASIC_IS_DCE41(rdev)) -- rdev->num_crtc = 2; -- else if (ASIC_IS_DCE4(rdev)) -- rdev->num_crtc = 6; -- else -- rdev->num_crtc = 2; -- } -- - return 0; - } - -diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c -index f116516..ce861ff 100644 ---- a/drivers/gpu/drm/radeon/radeon_atombios.c -+++ b/drivers/gpu/drm/radeon/radeon_atombios.c -@@ -1246,6 +1246,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) - } - *dcpll = *p1pll; - -+ rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock); -+ if (rdev->clock.max_pixel_clock == 0) -+ rdev->clock.max_pixel_clock = 40000; -+ - return true; - } - -@@ -2308,6 +2312,14 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, - le16_to_cpu(clock_info->r600.usVDDC); - } - -+ /* patch up vddc if necessary */ -+ if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) { -+ u16 vddc; -+ -+ if (radeon_atom_get_max_vddc(rdev, &vddc) == 0) -+ rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; -+ } -+ - if (rdev->flags & RADEON_IS_IGP) { - /* skip invalid modes */ - if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) -@@ -2595,6 +2607,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v - if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) - return; - -+ /* 0xff01 is a flag rather then an actual voltage */ -+ if (voltage_level == 0xff01) -+ return; -+ - switch (crev) { - case 1: - args.v1.ucVoltageType = voltage_type; -@@ -2614,7 +2630,35 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v - atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); - } - -+int radeon_atom_get_max_vddc(struct radeon_device *rdev, -+ u16 *voltage) -+{ -+ union set_voltage args; -+ int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); -+ u8 frev, crev; -+ -+ if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) -+ return -EINVAL; - -+ switch (crev) { -+ case 1: -+ return -EINVAL; -+ case 2: -+ args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; -+ args.v2.ucVoltageMode = 0; -+ args.v2.usVoltageLevel = 0; -+ -+ atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); -+ -+ *voltage = le16_to_cpu(args.v2.usVoltageLevel); -+ break; -+ default: -+ DRM_ERROR("Unknown table version %d, %d\n", frev, crev); -+ return -EINVAL; -+ } -+ -+ return 0; -+} - - void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) - { -diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c -index 5249af8..2d48e7a 100644 ---- a/drivers/gpu/drm/radeon/radeon_clocks.c -+++ b/drivers/gpu/drm/radeon/radeon_clocks.c -@@ -117,7 +117,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) - p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; - if (p1pll->reference_div < 2) - p1pll->reference_div = 12; -- p2pll->reference_div = p1pll->reference_div; -+ p2pll->reference_div = p1pll->reference_div; - - /* These aren't in the device-tree */ - if (rdev->family >= CHIP_R420) { -@@ -139,6 +139,8 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) - p2pll->pll_out_min = 12500; - p2pll->pll_out_max = 35000; - } -+ /* not sure what the max should be in all cases */ -+ rdev->clock.max_pixel_clock = 35000; - - spll->reference_freq = mpll->reference_freq = p1pll->reference_freq; - spll->reference_div = mpll->reference_div = -@@ -151,7 +153,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) - else - rdev->clock.default_sclk = - radeon_legacy_get_engine_clock(rdev); -- -+ - val = of_get_property(dp, "ATY,MCLK", NULL); - if (val && *val) - rdev->clock.default_mclk = (*val) / 10; -@@ -160,7 +162,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev) - radeon_legacy_get_memory_clock(rdev); - - DRM_INFO("Using device-tree clock info\n"); -- -+ - return true; - } - #else -diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c -index 089ab92..8a53691 100644 ---- a/drivers/gpu/drm/radeon/radeon_combios.c -+++ b/drivers/gpu/drm/radeon/radeon_combios.c -@@ -833,6 +833,11 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) - rdev->clock.default_sclk = sclk; - rdev->clock.default_mclk = mclk; - -+ if (RBIOS32(pll_info + 0x16)) -+ rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16); -+ else -+ rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */ -+ - return true; - } - return false; -diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c -index a186673..33cb72b 100644 ---- a/drivers/gpu/drm/radeon/radeon_connectors.c -+++ b/drivers/gpu/drm/radeon/radeon_connectors.c -@@ -621,8 +621,14 @@ static int radeon_vga_get_modes(struct drm_connector *connector) - static int radeon_vga_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) - { -+ struct drm_device *dev = connector->dev; -+ struct radeon_device *rdev = dev->dev_private; -+ - /* XXX check mode bandwidth */ -- /* XXX verify against max DAC output frequency */ -+ -+ if ((mode->clock / 10) > rdev->clock.max_pixel_clock) -+ return MODE_CLOCK_HIGH; -+ - return MODE_OK; - } - -@@ -1010,6 +1016,11 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector, - } else - return MODE_CLOCK_HIGH; - } -+ -+ /* check against the max pixel clock */ -+ if ((mode->clock / 10) > rdev->clock.max_pixel_clock) -+ return MODE_CLOCK_HIGH; -+ - return MODE_OK; - } - -diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c -index 207d43f..8a64a3b 100644 ---- a/drivers/gpu/drm/radeon/radeon_device.c -+++ b/drivers/gpu/drm/radeon/radeon_device.c -@@ -213,6 +213,8 @@ int radeon_wb_init(struct radeon_device *rdev) - return r; - } - -+ /* clear wb memory */ -+ memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE); - /* disable event_write fences */ - rdev->wb.use_event = false; - /* disabled via module param */ -@@ -752,6 +754,7 @@ int radeon_device_init(struct radeon_device *rdev, - dma_bits = rdev->need_dma32 ? 32 : 40; - r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); - if (r) { -+ rdev->need_dma32 = true; - printk(KERN_WARNING "radeon: No suitable DMA available.\n"); - } - -diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c -index b427488..e2a1c7d 100644 ---- a/drivers/gpu/drm/radeon/radeon_encoders.c -+++ b/drivers/gpu/drm/radeon/radeon_encoders.c -@@ -994,9 +994,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t - break; - } - -- if (is_dp) -+ if (is_dp) { - args.v2.acConfig.fCoherentMode = 1; -- else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { -+ args.v2.acConfig.fDPConnector = 1; -+ } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { - if (dig->coherent_mode) - args.v2.acConfig.fCoherentMode = 1; - if (radeon_encoder->pixel_clock > 165000) -@@ -1294,7 +1295,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) - if (is_dig) { - switch (mode) { - case DRM_MODE_DPMS_ON: -- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); -+ /* some early dce3.2 boards have a bug in their transmitter control table */ -+ if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) -+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); -+ else -+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); - if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - -diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c -index 2b0ee62..3285de1 100644 ---- a/drivers/gpu/drm/radeon/radeon_fence.c -+++ b/drivers/gpu/drm/radeon/radeon_fence.c -@@ -40,6 +40,35 @@ - #include "radeon.h" - #include "radeon_trace.h" - -+static void radeon_fence_write(struct radeon_device *rdev, u32 seq) -+{ -+ if (rdev->wb.enabled) { -+ u32 scratch_index; -+ if (rdev->wb.use_event) -+ scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -+ else -+ scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -+ rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);; -+ } else -+ WREG32(rdev->fence_drv.scratch_reg, seq); -+} -+ -+static u32 radeon_fence_read(struct radeon_device *rdev) -+{ -+ u32 seq; -+ -+ if (rdev->wb.enabled) { -+ u32 scratch_index; -+ if (rdev->wb.use_event) -+ scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -+ else -+ scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -+ seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); -+ } else -+ seq = RREG32(rdev->fence_drv.scratch_reg); -+ return seq; -+} -+ - int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) - { - unsigned long irq_flags; -@@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) - return 0; - } - fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); -- if (!rdev->cp.ready) { -+ if (!rdev->cp.ready) - /* FIXME: cp is not running assume everythings is done right - * away - */ -- WREG32(rdev->fence_drv.scratch_reg, fence->seq); -- } else -+ radeon_fence_write(rdev, fence->seq); -+ else - radeon_fence_ring_emit(rdev, fence); - - trace_radeon_fence_emit(rdev->ddev, fence->seq); -@@ -74,15 +103,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev) - bool wake = false; - unsigned long cjiffies; - -- if (rdev->wb.enabled) { -- u32 scratch_index; -- if (rdev->wb.use_event) -- scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -- else -- scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -- seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); -- } else -- seq = RREG32(rdev->fence_drv.scratch_reg); -+ seq = radeon_fence_read(rdev); - if (seq != rdev->fence_drv.last_seq) { - rdev->fence_drv.last_seq = seq; - rdev->fence_drv.last_jiffies = jiffies; -@@ -253,7 +274,7 @@ retry: - r = radeon_gpu_reset(rdev); - if (r) - return r; -- WREG32(rdev->fence_drv.scratch_reg, fence->seq); -+ radeon_fence_write(rdev, fence->seq); - rdev->gpu_lockup = false; - } - timeout = RADEON_FENCE_JIFFIES_TIMEOUT; -@@ -353,7 +374,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev) - write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); - return r; - } -- WREG32(rdev->fence_drv.scratch_reg, 0); -+ radeon_fence_write(rdev, 0); - atomic_set(&rdev->fence_drv.seq, 0); - INIT_LIST_HEAD(&rdev->fence_drv.created); - INIT_LIST_HEAD(&rdev->fence_drv.emited); -@@ -393,7 +414,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data) - struct radeon_fence *fence; - - seq_printf(m, "Last signaled fence 0x%08X\n", -- RREG32(rdev->fence_drv.scratch_reg)); -+ radeon_fence_read(rdev)); - if (!list_empty(&rdev->fence_drv.emited)) { - fence = list_entry(rdev->fence_drv.emited.prev, - struct radeon_fence, list); -diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c -index 114e5cc..cd9578b 100644 ---- a/drivers/gpu/drm/radeon/rv770.c -+++ b/drivers/gpu/drm/radeon/rv770.c -@@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev) - struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; - - if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { -+ /* 0xff01 is a flag rather then an actual voltage */ -+ if (voltage->voltage == 0xff01) -+ return; - if (voltage->voltage != rdev->pm.current_vddc) { - radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); - rdev->pm.current_vddc = voltage->voltage; diff --git a/drm-ttm-move-notify.patch b/drm-ttm-move-notify.patch deleted file mode 100644 index 4d4206fdc..000000000 --- a/drm-ttm-move-notify.patch +++ /dev/null @@ -1,40 +0,0 @@ -From e40ec45d67d32ce900dd6f2242675979593db18c Mon Sep 17 00:00:00 2001 -From: Ben Skeggs -Date: Tue, 18 Jan 2011 11:04:03 +1000 -Subject: [PATCH] drm/ttm: call driver move_notify() when doing system->tt bo moves - -Nouveau doesn't have enough information at ttm_backend_func.bind() time -to implement things like tiled GART, or to keep a buffer at a constant -address in the GPU virtual address space no matter where in physical -memory it's placed. - -To resolve this, nouveau will handle binding of all buffers to the GPU -itself from the move_notify() hook. This commit ensures it's called -for all buffer moves. - -Signed-off-by: Ben Skeggs ---- - drivers/gpu/drm/ttm/ttm_bo.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c -index af61fc2..0b6a55a 100644 ---- a/drivers/gpu/drm/ttm/ttm_bo.c -+++ b/drivers/gpu/drm/ttm/ttm_bo.c -@@ -406,11 +406,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, - } - - if (bo->mem.mem_type == TTM_PL_SYSTEM) { -+ if (bdev->driver->move_notify) -+ bdev->driver->move_notify(bo, mem); - bo->mem = *mem; - mem->mm_node = NULL; - goto moved; - } -- - } - - if (bdev->driver->move_notify) --- -1.7.4.2 - diff --git a/efifb_update.patch b/efifb_update.patch deleted file mode 100644 index 7058ba610..000000000 --- a/efifb_update.patch +++ /dev/null @@ -1,217 +0,0 @@ -Fix up efifb so it works properly on the 11" Macbook Air. Upstream in .38? - -diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c -index 70477c2..476ffb1 100644 ---- a/drivers/video/efifb.c -+++ b/drivers/video/efifb.c -@@ -53,6 +53,7 @@ enum { - M_MB_7_1, /* MacBook, 7th rev. */ - M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ - M_MBA, /* MacBook Air */ -+ M_MBA_3, /* Macbook Air, 3rd rev */ - M_MBP, /* MacBook Pro */ - M_MBP_2, /* MacBook Pro 2nd gen */ - M_MBP_2_2, /* MacBook Pro 2,2nd gen */ -@@ -67,40 +68,49 @@ enum { - M_UNKNOWN /* placeholder */ - }; - -+#define OVERRIDE_NONE 0x0 -+#define OVERRIDE_BASE 0x1 -+#define OVERRIDE_STRIDE 0x2 -+#define OVERRIDE_HEIGHT 0x4 -+#define OVERRIDE_WIDTH 0x8 -+ - static struct efifb_dmi_info { - char *optname; - unsigned long base; - int stride; - int width; - int height; -+ int flags; - } dmi_list[] __initdata = { -- [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900 }, -- [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ -- [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, -- [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ -- [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, -- [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, -- [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, -- [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, -- [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, -- [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, -- [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, -- [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, -- [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, -- [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, -- [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, -- [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, -- [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ -- [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, -- [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, -- [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, -- [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, -- [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, -- [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, -- [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, -- [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, -- [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, -- [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } -+ [M_I17] = { "i17", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, -+ [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, /* guess */ -+ [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050, OVERRIDE_NONE }, -+ [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, /* guess */ -+ [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, -+ [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080, OVERRIDE_NONE }, -+ [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440, OVERRIDE_NONE }, -+ [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768, OVERRIDE_NONE }, -+ [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768, OVERRIDE_NONE }, -+ [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, -+ [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, -+ [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, -+ [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, -+ [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, -+ [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, -+ /* 11" Macbook Air 3,1 passes the wrong stride */ -+ [M_MBA_3] = { "mba3", 0, 2048 * 4, 0, 0, OVERRIDE_STRIDE }, -+ [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, -+ [M_MBP_2] = { "mbp2", 0, 0, 0, 0, OVERRIDE_NONE }, /* placeholder */ -+ [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900, OVERRIDE_NONE }, -+ [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, -+ [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, -+ [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, -+ [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, -+ [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900, OVERRIDE_NONE }, -+ [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200, OVERRIDE_NONE }, -+ [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050, OVERRIDE_NONE }, -+ [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800, OVERRIDE_NONE }, -+ [M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE } - }; - - static int set_system(const struct dmi_system_id *id); -@@ -138,6 +148,7 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), - EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), -+ EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir3,1", M_MBA_3), - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), - EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), -@@ -154,16 +165,22 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { - {}, - }; - -+#define choose_value(dmivalue, fwvalue, field, flags) ({ \ -+ typeof(fwvalue) _ret_ = fwvalue; \ -+ if ((flags) & (field)) \ -+ _ret_ = dmivalue; \ -+ else if ((fwvalue) == 0) \ -+ _ret_ = dmivalue; \ -+ _ret_; \ -+ }) -+ - static int set_system(const struct dmi_system_id *id) - { - struct efifb_dmi_info *info = id->driver_data; -- if (info->base == 0) -- return 0; - -- printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " -- "(%dx%d, stride %d)\n", id->ident, -- (void *)info->base, info->width, info->height, -- info->stride); -+ if (info->base == 0 && info->height == 0 && info->width == 0 -+ && info->stride == 0) -+ return 0; - - /* Trust the bootloader over the DMI tables */ - if (screen_info.lfb_base == 0) { -@@ -171,40 +188,47 @@ static int set_system(const struct dmi_system_id *id) - struct pci_dev *dev = NULL; - int found_bar = 0; - #endif -- screen_info.lfb_base = info->base; -+ if (info->base) { -+ screen_info.lfb_base = choose_value(info->base, -+ screen_info.lfb_base, OVERRIDE_BASE, -+ info->flags); - - #if defined(CONFIG_PCI) -- /* make sure that the address in the table is actually on a -- * VGA device's PCI BAR */ -- -- for_each_pci_dev(dev) { -- int i; -- if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) -- continue; -- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { -- resource_size_t start, end; -- -- start = pci_resource_start(dev, i); -- if (start == 0) -- break; -- end = pci_resource_end(dev, i); -- if (screen_info.lfb_base >= start && -- screen_info.lfb_base < end) { -- found_bar = 1; -+ /* make sure that the address in the table is actually -+ * on a VGA device's PCI BAR */ -+ -+ for_each_pci_dev(dev) { -+ int i; -+ if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) -+ continue; -+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { -+ resource_size_t start, end; -+ -+ start = pci_resource_start(dev, i); -+ if (start == 0) -+ break; -+ end = pci_resource_end(dev, i); -+ if (screen_info.lfb_base >= start && -+ screen_info.lfb_base < end) { -+ found_bar = 1; -+ } - } - } -- } -- if (!found_bar) -- screen_info.lfb_base = 0; -+ if (!found_bar) -+ screen_info.lfb_base = 0; - #endif -+ } - } - if (screen_info.lfb_base) { -- if (screen_info.lfb_linelength == 0) -- screen_info.lfb_linelength = info->stride; -- if (screen_info.lfb_width == 0) -- screen_info.lfb_width = info->width; -- if (screen_info.lfb_height == 0) -- screen_info.lfb_height = info->height; -+ screen_info.lfb_linelength = choose_value(info->stride, -+ screen_info.lfb_linelength, OVERRIDE_STRIDE, -+ info->flags); -+ screen_info.lfb_width = choose_value(info->width, -+ screen_info.lfb_width, OVERRIDE_WIDTH, -+ info->flags); -+ screen_info.lfb_height = choose_value(info->height, -+ screen_info.lfb_height, OVERRIDE_HEIGHT, -+ info->flags); - if (screen_info.orig_video_isVGA == 0) - screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; - } else { -@@ -214,6 +238,13 @@ static int set_system(const struct dmi_system_id *id) - screen_info.orig_video_isVGA = 0; - return 0; - } -+ -+ printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " -+ "(%dx%d, stride %d)\n", id->ident, -+ (void *)screen_info.lfb_base, screen_info.lfb_width, -+ screen_info.lfb_height, screen_info.lfb_linelength); -+ -+ - return 1; - } - diff --git a/git-linus.diff b/git-linus.diff deleted file mode 100644 index e69de29bb..000000000 diff --git a/hid-multitouch-add-support-for-elo-touchsystems.patch b/hid-multitouch-add-support-for-elo-touchsystems.patch index 1294f4630..789201f81 100644 --- a/hid-multitouch-add-support-for-elo-touchsystems.patch +++ b/hid-multitouch-add-support-for-elo-touchsystems.patch @@ -1,30 +1,2205 @@ -From: Benjamin Tissoires -Date: Thu, 19 May 2011 09:37:29 +0000 (+0200) -Subject: HID: hid-multitouch: add support for Elo TouchSystems 2515 IntelliTouch Plus -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjikos%2Fhid.git;a=commitdiff_plain;h=c04abeeff9d76a703cac1e6d312853b0fc8136f5 +commit 9498f954a4ec389806333041a1018909c6fe0518 +Author: Benjamin Tissoires +Date: Fri Mar 18 14:27:52 2011 +0100 -HID: hid-multitouch: add support for Elo TouchSystems 2515 IntelliTouch Plus + HID: hid-multitouch: Auto detection of maxcontacts + + This patch enables support of autodetection of maxcontacts. + When adding support for a new device, one is now able to let + the device tell how many contacts it supports, or to manually + set the value if the device happens to provide wrong information. + + Signed-off-by: Benjamin Tissoires + Reviewed-by: Stéphane Chatty + Reviewed-by: Henrik Rydberg + Signed-off-by: Jiri Kosina -This patch adds support for Elo TouchSystems 2515 IntelliTouch Plus -that can be found in Lenovo A700 all-in-one. +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index ee01e65..b9f9eec 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -60,8 +60,9 @@ struct mt_device { + __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ + __u8 num_received; /* how many contacts we received */ + __u8 num_expected; /* expected last contact index */ ++ __u8 maxcontacts; + bool curvalid; /* is the current contact valid? */ +- struct mt_slot slots[0]; /* first slot */ ++ struct mt_slot *slots; + }; + + struct mt_class { +@@ -79,6 +80,8 @@ struct mt_class { + #define MT_CLS_CYPRESS 4 + #define MT_CLS_EGALAX 5 + ++#define MT_DEFAULT_MAXCONTACT 10 ++ + /* + * these device-dependent functions determine what slot corresponds + * to a valid contact that was just read. +@@ -95,12 +98,12 @@ static int cypress_compute_slot(struct mt_device *td) + static int find_slot_from_contactid(struct mt_device *td) + { + int i; +- for (i = 0; i < td->mtclass->maxcontacts; ++i) { ++ for (i = 0; i < td->maxcontacts; ++i) { + if (td->slots[i].contactid == td->curdata.contactid && + td->slots[i].touch_state) + return i; + } +- for (i = 0; i < td->mtclass->maxcontacts; ++i) { ++ for (i = 0; i < td->maxcontacts; ++i) { + if (!td->slots[i].seen_in_this_frame && + !td->slots[i].touch_state) + return i; +@@ -113,8 +116,7 @@ static int find_slot_from_contactid(struct mt_device *td) + + struct mt_class mt_classes[] = { + { .name = MT_CLS_DEFAULT, +- .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP, +- .maxcontacts = 10 }, ++ .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, + { .name = MT_CLS_DUAL_INRANGE_CONTACTID, + .quirks = MT_QUIRK_VALID_IS_INRANGE | + MT_QUIRK_SLOT_IS_CONTACTID, +@@ -142,9 +144,19 @@ struct mt_class mt_classes[] = { + static void mt_feature_mapping(struct hid_device *hdev, + struct hid_field *field, struct hid_usage *usage) + { +- if (usage->hid == HID_DG_INPUTMODE) { +- struct mt_device *td = hid_get_drvdata(hdev); ++ struct mt_device *td = hid_get_drvdata(hdev); ++ ++ switch (usage->hid) { ++ case HID_DG_INPUTMODE: + td->inputmode = field->report->id; ++ break; ++ case HID_DG_CONTACTMAX: ++ td->maxcontacts = field->value[0]; ++ if (td->mtclass->maxcontacts) ++ /* check if the maxcontacts is given by the class */ ++ td->maxcontacts = td->mtclass->maxcontacts; ++ ++ break; + } + } + +@@ -208,8 +220,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + td->last_slot_field = usage->hid; + return 1; + case HID_DG_CONTACTID: +- input_mt_init_slots(hi->input, +- td->mtclass->maxcontacts); ++ input_mt_init_slots(hi->input, td->maxcontacts); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_WIDTH: +@@ -292,7 +303,7 @@ static void mt_complete_slot(struct mt_device *td) + if (td->curvalid) { + int slotnum = mt_compute_slot(td); + +- if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts) ++ if (slotnum >= 0 && slotnum < td->maxcontacts) + td->slots[slotnum] = td->curdata; + } + td->num_received++; +@@ -307,7 +318,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) + { + int i; + +- for (i = 0; i < td->mtclass->maxcontacts; ++i) { ++ for (i = 0; i < td->maxcontacts; ++i) { + struct mt_slot *s = &(td->slots[i]); + if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && + !s->seen_in_this_frame) { +@@ -341,7 +352,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, + struct mt_device *td = hid_get_drvdata(hid); + __s32 quirks = td->mtclass->quirks; + +- if (hid->claimed & HID_CLAIMED_INPUT) { ++ if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { + switch (usage->hid) { + case HID_DG_INRANGE: + if (quirks & MT_QUIRK_VALID_IS_INRANGE) +@@ -442,9 +453,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) + */ + hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; + +- td = kzalloc(sizeof(struct mt_device) + +- mtclass->maxcontacts * sizeof(struct mt_slot), +- GFP_KERNEL); ++ td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); + if (!td) { + dev_err(&hdev->dev, "cannot allocate multitouch data\n"); + return -ENOMEM; +@@ -461,6 +470,18 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) + if (ret) + goto fail; + ++ if (!td->maxcontacts) ++ td->maxcontacts = MT_DEFAULT_MAXCONTACT; ++ ++ td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), ++ GFP_KERNEL); ++ if (!td->slots) { ++ dev_err(&hdev->dev, "cannot allocate multitouch slots\n"); ++ hid_hw_stop(hdev); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ + mt_set_input_mode(hdev); + + return 0; +@@ -482,6 +503,7 @@ static void mt_remove(struct hid_device *hdev) + { + struct mt_device *td = hid_get_drvdata(hdev); + hid_hw_stop(hdev); ++ kfree(td->slots); + kfree(td); + hid_set_drvdata(hdev, NULL); + } +commit 043b403aede4a528ed99ceaf050f567f1283a23e +Author: Benjamin Tissoires +Date: Fri Mar 18 14:27:53 2011 +0100 -Signed-off-by: Benjamin Tissoires -Tested-by: Bastien Nocera -Signed-off-by: Jiri Kosina + HID: hid-multitouch: migrate support for Stantum panels to the unified driver. + + This patch merges hid-stantum to the generic multitouch driver. + + Signed-off-by: Benjamin Tissoires + Reviewed-by: Stéphane Chatty + Reviewed-by: Henrik Rydberg + Signed-off-by: Jiri Kosina +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index b7ec405..3c72f16 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig -@@ -309,6 +309,7 @@ config HID_MULTITOUCH +@@ -327,6 +327,7 @@ config HID_MULTITOUCH + - 'Sensing Win7-TwoFinger' panel by GeneralTouch + - eGalax dual-touch panels, including the + Joojoo and Wetab tablets ++ - Stantum multitouch panels + + If unsure, say N. + +@@ -493,12 +494,6 @@ config HID_SONY + ---help--- + Support for Sony PS3 controller. + +-config HID_STANTUM +- tristate "Stantum multitouch panel" +- depends on USB_HID +- ---help--- +- Support for Stantum multitouch panel. +- + config HID_SUNPLUS + tristate "Sunplus wireless desktop" + depends on USB_HID +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 06c68ae..a13cb4e 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -66,7 +66,6 @@ obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o + obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o + obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o + obj-$(CONFIG_HID_SONY) += hid-sony.o +-obj-$(CONFIG_HID_STANTUM) += hid-stantum.o + obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o + obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o + obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index b9f9eec..5983e55 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -79,6 +79,7 @@ struct mt_class { + #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 3 + #define MT_CLS_CYPRESS 4 + #define MT_CLS_EGALAX 5 ++#define MT_CLS_STANTUM 6 + + #define MT_DEFAULT_MAXCONTACT 10 + +@@ -138,6 +139,9 @@ struct mt_class mt_classes[] = { + .sn_move = 4096, + .sn_pressure = 32, + }, ++ { .name = MT_CLS_STANTUM, ++ .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, ++ + { } + }; + +@@ -552,6 +556,17 @@ static const struct hid_device_id mt_devices[] = { + HID_USB_DEVICE(USB_VENDOR_ID_DWAV, + USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, + ++ /* Stantum panels */ ++ { .driver_data = MT_CLS_STANTUM, ++ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, ++ USB_DEVICE_ID_MTP)}, ++ { .driver_data = MT_CLS_STANTUM, ++ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, ++ USB_DEVICE_ID_MTP_STM)}, ++ { .driver_data = MT_CLS_STANTUM, ++ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, ++ USB_DEVICE_ID_MTP_SITRONIX)}, ++ + { } + }; + MODULE_DEVICE_TABLE(hid, mt_devices); +diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c +deleted file mode 100644 +index b2be1d1..0000000 +--- a/drivers/hid/hid-stantum.c ++++ /dev/null +@@ -1,286 +0,0 @@ +-/* +- * HID driver for Stantum multitouch panels +- * +- * Copyright (c) 2009 Stephane Chatty +- * +- */ +- +-/* +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the Free +- * Software Foundation; either version 2 of the License, or (at your option) +- * any later version. +- */ +- +-#include +-#include +-#include +-#include +- +-MODULE_AUTHOR("Stephane Chatty "); +-MODULE_DESCRIPTION("Stantum HID multitouch panels"); +-MODULE_LICENSE("GPL"); +- +-#include "hid-ids.h" +- +-struct stantum_data { +- __s32 x, y, z, w, h; /* x, y, pressure, width, height */ +- __u16 id; /* touch id */ +- bool valid; /* valid finger data, or just placeholder? */ +- bool first; /* first finger in the HID packet? */ +- bool activity; /* at least one active finger so far? */ +-}; +- +-static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- switch (usage->hid & HID_USAGE_PAGE) { +- +- case HID_UP_GENDESK: +- switch (usage->hid) { +- case HID_GD_X: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_X); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_X, +- field->logical_minimum, +- field->logical_maximum, 0, 0); +- return 1; +- case HID_GD_Y: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_Y); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_Y, +- field->logical_minimum, +- field->logical_maximum, 0, 0); +- return 1; +- } +- return 0; +- +- case HID_UP_DIGITIZER: +- switch (usage->hid) { +- case HID_DG_INRANGE: +- case HID_DG_CONFIDENCE: +- case HID_DG_INPUTMODE: +- case HID_DG_DEVICEINDEX: +- case HID_DG_CONTACTCOUNT: +- case HID_DG_CONTACTMAX: +- return -1; +- +- case HID_DG_TIPSWITCH: +- /* touchscreen emulation */ +- hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); +- return 1; +- +- case HID_DG_WIDTH: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_TOUCH_MAJOR); +- return 1; +- case HID_DG_HEIGHT: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_TOUCH_MINOR); +- input_set_abs_params(hi->input, ABS_MT_ORIENTATION, +- 1, 1, 0, 0); +- return 1; +- case HID_DG_TIPPRESSURE: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_PRESSURE); +- return 1; +- +- case HID_DG_CONTACTID: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_TRACKING_ID); +- return 1; +- +- } +- return 0; +- +- case 0xff000000: +- /* no input-oriented meaning */ +- return -1; +- } +- +- return 0; +-} +- +-static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- if (usage->type == EV_KEY || usage->type == EV_ABS) +- clear_bit(usage->code, *bit); +- +- return 0; +-} +- +-/* +- * this function is called when a whole finger has been parsed, +- * so that it can decide what to send to the input layer. +- */ +-static void stantum_filter_event(struct stantum_data *sd, +- struct input_dev *input) +-{ +- bool wide; +- +- if (!sd->valid) { +- /* +- * touchscreen emulation: if the first finger is not valid and +- * there previously was finger activity, this is a release +- */ +- if (sd->first && sd->activity) { +- input_event(input, EV_KEY, BTN_TOUCH, 0); +- sd->activity = false; +- } +- return; +- } +- +- input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id); +- input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x); +- input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y); +- +- wide = (sd->w > sd->h); +- input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); +- input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h); +- input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w); +- +- input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z); +- +- input_mt_sync(input); +- sd->valid = false; +- +- /* touchscreen emulation */ +- if (sd->first) { +- if (!sd->activity) { +- input_event(input, EV_KEY, BTN_TOUCH, 1); +- sd->activity = true; +- } +- input_event(input, EV_ABS, ABS_X, sd->x); +- input_event(input, EV_ABS, ABS_Y, sd->y); +- } +- sd->first = false; +-} +- +- +-static int stantum_event(struct hid_device *hid, struct hid_field *field, +- struct hid_usage *usage, __s32 value) +-{ +- struct stantum_data *sd = hid_get_drvdata(hid); +- +- if (hid->claimed & HID_CLAIMED_INPUT) { +- struct input_dev *input = field->hidinput->input; +- +- switch (usage->hid) { +- case HID_DG_INRANGE: +- /* this is the last field in a finger */ +- stantum_filter_event(sd, input); +- break; +- case HID_DG_WIDTH: +- sd->w = value; +- break; +- case HID_DG_HEIGHT: +- sd->h = value; +- break; +- case HID_GD_X: +- sd->x = value; +- break; +- case HID_GD_Y: +- sd->y = value; +- break; +- case HID_DG_TIPPRESSURE: +- sd->z = value; +- break; +- case HID_DG_CONTACTID: +- sd->id = value; +- break; +- case HID_DG_CONFIDENCE: +- sd->valid = !!value; +- break; +- case 0xff000002: +- /* this comes only before the first finger */ +- sd->first = true; +- break; +- +- default: +- /* ignore the others */ +- return 1; +- } +- } +- +- /* we have handled the hidinput part, now remains hiddev */ +- if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) +- hid->hiddev_hid_event(hid, field, usage, value); +- +- return 1; +-} +- +-static int stantum_probe(struct hid_device *hdev, +- const struct hid_device_id *id) +-{ +- int ret; +- struct stantum_data *sd; +- +- sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL); +- if (!sd) { +- hid_err(hdev, "cannot allocate Stantum data\n"); +- return -ENOMEM; +- } +- sd->valid = false; +- sd->first = false; +- sd->activity = false; +- hid_set_drvdata(hdev, sd); +- +- ret = hid_parse(hdev); +- if (!ret) +- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); +- +- if (ret) +- kfree(sd); +- +- return ret; +-} +- +-static void stantum_remove(struct hid_device *hdev) +-{ +- hid_hw_stop(hdev); +- kfree(hid_get_drvdata(hdev)); +- hid_set_drvdata(hdev, NULL); +-} +- +-static const struct hid_device_id stantum_devices[] = { +- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) }, +- { } +-}; +-MODULE_DEVICE_TABLE(hid, stantum_devices); +- +-static const struct hid_usage_id stantum_grabbed_usages[] = { +- { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, +- { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} +-}; +- +-static struct hid_driver stantum_driver = { +- .name = "stantum", +- .id_table = stantum_devices, +- .probe = stantum_probe, +- .remove = stantum_remove, +- .input_mapping = stantum_input_mapping, +- .input_mapped = stantum_input_mapped, +- .usage_table = stantum_grabbed_usages, +- .event = stantum_event, +-}; +- +-static int __init stantum_init(void) +-{ +- return hid_register_driver(&stantum_driver); +-} +- +-static void __exit stantum_exit(void) +-{ +- hid_unregister_driver(&stantum_driver); +-} +- +-module_init(stantum_init); +-module_exit(stantum_exit); +- +commit a841b62c5d5f75ce3676fde755696d30cc8de99a +Author: Benjamin Tissoires +Date: Fri Mar 18 14:27:54 2011 +0100 + + HID: hid-multitouch: migrate Cando dual touch panels to hid-multitouch + + This patch merges hid-cando into the unified multitouch driver. + + Signed-off-by: Benjamin Tissoires + Reviewed-by: Stéphane Chatty + Reviewed-by: Henrik Rydberg + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 3c72f16..1edb0bd 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -100,12 +100,6 @@ config HID_BELKIN + ---help--- + Support for Belkin Flip KVM and Wireless keyboard. + +-config HID_CANDO +- tristate "Cando dual touch panel" +- depends on USB_HID +- ---help--- +- Support for Cando dual touch panel. +- + config HID_CHERRY + tristate "Cherry Cymotion keyboard" if EXPERT + depends on USB_HID +@@ -320,6 +314,7 @@ config HID_MULTITOUCH + Generic support for HID multitouch panels. Say Y here if you have one of the following devices: ++ - Cando dual touch panel + - Cypress TrueTouch panels + - Hanvon dual touch panels + - IrTouch Infrared USB panels +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index a13cb4e..f8b90e4 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -30,7 +30,6 @@ obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o + obj-$(CONFIG_HID_ACRUX) += hid-axff.o + obj-$(CONFIG_HID_APPLE) += hid-apple.o + obj-$(CONFIG_HID_BELKIN) += hid-belkin.o +-obj-$(CONFIG_HID_CANDO) += hid-cando.o + obj-$(CONFIG_HID_CHERRY) += hid-cherry.o + obj-$(CONFIG_HID_CHICONY) += hid-chicony.o + obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o +diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c +deleted file mode 100644 +index 1ea066c..0000000 +--- a/drivers/hid/hid-cando.c ++++ /dev/null +@@ -1,276 +0,0 @@ +-/* +- * HID driver for Cando dual-touch panels +- * +- * Copyright (c) 2010 Stephane Chatty +- * +- */ +- +-/* +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the Free +- * Software Foundation; either version 2 of the License, or (at your option) +- * any later version. +- */ +- +-#include +-#include +-#include +-#include +- +-MODULE_AUTHOR("Stephane Chatty "); +-MODULE_DESCRIPTION("Cando dual-touch panel"); +-MODULE_LICENSE("GPL"); +- +-#include "hid-ids.h" +- +-struct cando_data { +- __u16 x, y; +- __u8 id; +- __s8 oldest; /* id of the oldest finger in previous frame */ +- bool valid; /* valid finger data, or just placeholder? */ +- bool first; /* is this the first finger in this frame? */ +- __s8 firstid; /* id of the first finger in the frame */ +- __u16 firstx, firsty; /* (x, y) of the first finger in the frame */ +-}; +- +-static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- switch (usage->hid & HID_USAGE_PAGE) { +- +- case HID_UP_GENDESK: +- switch (usage->hid) { +- case HID_GD_X: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_X); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_X, +- field->logical_minimum, +- field->logical_maximum, 0, 0); +- return 1; +- case HID_GD_Y: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_Y); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_Y, +- field->logical_minimum, +- field->logical_maximum, 0, 0); +- return 1; +- } +- return 0; +- +- case HID_UP_DIGITIZER: +- switch (usage->hid) { +- case HID_DG_TIPSWITCH: +- case HID_DG_CONTACTMAX: +- return -1; +- case HID_DG_INRANGE: +- /* touchscreen emulation */ +- hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); +- return 1; +- case HID_DG_CONTACTID: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_TRACKING_ID); +- return 1; +- } +- return 0; +- } +- +- return 0; +-} +- +-static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- if (usage->type == EV_KEY || usage->type == EV_ABS) +- clear_bit(usage->code, *bit); +- +- return 0; +-} +- +-/* +- * this function is called when a whole finger has been parsed, +- * so that it can decide what to send to the input layer. +- */ +-static void cando_filter_event(struct cando_data *td, struct input_dev *input) +-{ +- td->first = !td->first; /* touchscreen emulation */ +- +- if (!td->valid) { +- /* +- * touchscreen emulation: if this is the second finger and +- * the first was valid, the first was the oldest; if the +- * first was not valid and there was a valid finger in the +- * previous frame, this is a release. +- */ +- if (td->first) { +- td->firstid = -1; +- } else if (td->firstid >= 0) { +- input_event(input, EV_ABS, ABS_X, td->firstx); +- input_event(input, EV_ABS, ABS_Y, td->firsty); +- td->oldest = td->firstid; +- } else if (td->oldest >= 0) { +- input_event(input, EV_KEY, BTN_TOUCH, 0); +- td->oldest = -1; +- } +- +- return; +- } +- +- input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); +- input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); +- input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); +- +- input_mt_sync(input); +- +- /* +- * touchscreen emulation: if there was no touching finger previously, +- * emit touch event +- */ +- if (td->oldest < 0) { +- input_event(input, EV_KEY, BTN_TOUCH, 1); +- td->oldest = td->id; +- } +- +- /* +- * touchscreen emulation: if this is the first finger, wait for the +- * second; the oldest is then the second if it was the oldest already +- * or if there was no first, the first otherwise. +- */ +- if (td->first) { +- td->firstx = td->x; +- td->firsty = td->y; +- td->firstid = td->id; +- } else { +- int x, y, oldest; +- if (td->id == td->oldest || td->firstid < 0) { +- x = td->x; +- y = td->y; +- oldest = td->id; +- } else { +- x = td->firstx; +- y = td->firsty; +- oldest = td->firstid; +- } +- input_event(input, EV_ABS, ABS_X, x); +- input_event(input, EV_ABS, ABS_Y, y); +- td->oldest = oldest; +- } +-} +- +- +-static int cando_event(struct hid_device *hid, struct hid_field *field, +- struct hid_usage *usage, __s32 value) +-{ +- struct cando_data *td = hid_get_drvdata(hid); +- +- if (hid->claimed & HID_CLAIMED_INPUT) { +- struct input_dev *input = field->hidinput->input; +- +- switch (usage->hid) { +- case HID_DG_INRANGE: +- td->valid = value; +- break; +- case HID_DG_CONTACTID: +- td->id = value; +- break; +- case HID_GD_X: +- td->x = value; +- break; +- case HID_GD_Y: +- td->y = value; +- cando_filter_event(td, input); +- break; +- case HID_DG_TIPSWITCH: +- /* avoid interference from generic hidinput handling */ +- break; +- +- default: +- /* fallback to the generic hidinput handling */ +- return 0; +- } +- } +- +- /* we have handled the hidinput part, now remains hiddev */ +- if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) +- hid->hiddev_hid_event(hid, field, usage, value); +- +- return 1; +-} +- +-static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id) +-{ +- int ret; +- struct cando_data *td; +- +- td = kmalloc(sizeof(struct cando_data), GFP_KERNEL); +- if (!td) { +- hid_err(hdev, "cannot allocate Cando Touch data\n"); +- return -ENOMEM; +- } +- hid_set_drvdata(hdev, td); +- td->first = false; +- td->oldest = -1; +- td->valid = false; +- +- ret = hid_parse(hdev); +- if (!ret) +- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); +- +- if (ret) +- kfree(td); +- +- return ret; +-} +- +-static void cando_remove(struct hid_device *hdev) +-{ +- hid_hw_stop(hdev); +- kfree(hid_get_drvdata(hdev)); +- hid_set_drvdata(hdev, NULL); +-} +- +-static const struct hid_device_id cando_devices[] = { +- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, +- USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, +- USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, +- USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, +- USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, +- { } +-}; +-MODULE_DEVICE_TABLE(hid, cando_devices); +- +-static const struct hid_usage_id cando_grabbed_usages[] = { +- { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, +- { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} +-}; +- +-static struct hid_driver cando_driver = { +- .name = "cando-touch", +- .id_table = cando_devices, +- .probe = cando_probe, +- .remove = cando_remove, +- .input_mapping = cando_input_mapping, +- .input_mapped = cando_input_mapped, +- .usage_table = cando_grabbed_usages, +- .event = cando_event, +-}; +- +-static int __init cando_init(void) +-{ +- return hid_register_driver(&cando_driver); +-} +- +-static void __exit cando_exit(void) +-{ +- hid_unregister_driver(&cando_driver); +-} +- +-module_init(cando_init); +-module_exit(cando_exit); +- +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 5983e55..e6e1ea2 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -514,6 +514,20 @@ static void mt_remove(struct hid_device *hdev) + + static const struct hid_device_id mt_devices[] = { + ++ /* Cando panels */ ++ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, ++ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, ++ USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, ++ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, ++ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, ++ USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, ++ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, ++ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, ++ USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, ++ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, ++ HID_USB_DEVICE(USB_VENDOR_ID_CANDO, ++ USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, ++ + /* Cypress panel */ + { .driver_data = MT_CLS_CYPRESS, + HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, +commit 1e648a13720ef5de51f132501acf3e443d1a36d4 +Author: Benjamin Tissoires +Date: Fri Mar 18 14:27:55 2011 +0100 + + HID: hid-multitouch: refactor initialization of ABS_MT_ORIENTATION + + The way the input_set_abs_params was called for the new composite field + ABS_MT_ORIENTATION was not very clear at second reading. We can remove the + non-necessary call to set_abs and use the simple call to input_set_abs_params. + + Signed-off-by: Benjamin Tissoires + Reviewed-by: Stéphane Chatty + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index e6e1ea2..d31301e 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -235,9 +235,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + case HID_DG_HEIGHT: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TOUCH_MINOR); +- field->logical_maximum = 1; +- field->logical_minimum = 0; +- set_abs(hi->input, ABS_MT_ORIENTATION, field, 0); ++ input_set_abs_params(hi->input, ++ ABS_MT_ORIENTATION, 0, 1, 0, 0); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_TIPPRESSURE: +commit f786bba4499cf3de20da345ce090457ebcef03b0 +Author: Benjamin Tissoires +Date: Tue Mar 22 17:34:01 2011 +0100 + + HID: hid-multitouch: migrate 3M PCT touch screens to hid-multitouch + + This patch merges the hid-3m-pct driver into hid-multitouch. + To keep devices working the same way they used to with hid-3m-pct, + we need to add two signal/noise ratios for width and height. + We also need to work on width/height to send proper + ABS_MT_ORIENTATION flag. + + Importing 3M into hid-multitouch also solved the bug in which + devices handling width and height in their report descriptors + did not show ABS_MT_TOUCH_MAJOR and ABS_MT_TOUCH_MINOR. + + Signed-off-by: Benjamin Tissoires + Reviewed-by: Stéphane Chatty + Reviewed-and-tested-by: Henrik Rydberg + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 1edb0bd..996ae3a 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -55,12 +55,6 @@ source "drivers/hid/usbhid/Kconfig" + menu "Special HID drivers" + depends on HID + +-config HID_3M_PCT +- tristate "3M PCT touchscreen" +- depends on USB_HID +- ---help--- +- Support for 3M PCT touch screens. +- + config HID_A4TECH + tristate "A4 tech mice" if EXPERT + depends on USB_HID +@@ -314,6 +308,7 @@ config HID_MULTITOUCH + Generic support for HID multitouch panels. + + Say Y here if you have one of the following devices: ++ - 3M PCT touch screens + - Cando dual touch panel + - Cypress TrueTouch panels + - Hanvon dual touch panels +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index f8b90e4..11c9f0b 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -25,7 +25,6 @@ ifdef CONFIG_LOGIWII_FF + hid-logitech-y += hid-lg4ff.o + endif + +-obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o + obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o + obj-$(CONFIG_HID_ACRUX) += hid-axff.o + obj-$(CONFIG_HID_APPLE) += hid-apple.o +diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c +deleted file mode 100644 +index 5243ae2..0000000 +--- a/drivers/hid/hid-3m-pct.c ++++ /dev/null +@@ -1,305 +0,0 @@ +-/* +- * HID driver for 3M PCT multitouch panels +- * +- * Copyright (c) 2009-2010 Stephane Chatty +- * Copyright (c) 2010 Henrik Rydberg +- * Copyright (c) 2010 Canonical, Ltd. +- * +- */ +- +-/* +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the Free +- * Software Foundation; either version 2 of the License, or (at your option) +- * any later version. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-MODULE_AUTHOR("Stephane Chatty "); +-MODULE_DESCRIPTION("3M PCT multitouch panels"); +-MODULE_LICENSE("GPL"); +- +-#include "hid-ids.h" +- +-#define MAX_SLOTS 60 +- +-/* estimated signal-to-noise ratios */ +-#define SN_MOVE 2048 +-#define SN_WIDTH 128 +- +-struct mmm_finger { +- __s32 x, y, w, h; +- bool touch, valid; +-}; +- +-struct mmm_data { +- struct mmm_finger f[MAX_SLOTS]; +- __u8 curid; +- __u8 nexp, nreal; +- bool touch, valid; +-}; +- +-static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- int f1 = field->logical_minimum; +- int f2 = field->logical_maximum; +- int df = f2 - f1; +- +- switch (usage->hid & HID_USAGE_PAGE) { +- +- case HID_UP_BUTTON: +- return -1; +- +- case HID_UP_GENDESK: +- switch (usage->hid) { +- case HID_GD_X: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_X); +- input_set_abs_params(hi->input, ABS_MT_POSITION_X, +- f1, f2, df / SN_MOVE, 0); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_X, +- f1, f2, df / SN_MOVE, 0); +- return 1; +- case HID_GD_Y: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_Y); +- input_set_abs_params(hi->input, ABS_MT_POSITION_Y, +- f1, f2, df / SN_MOVE, 0); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_Y, +- f1, f2, df / SN_MOVE, 0); +- return 1; +- } +- return 0; +- +- case HID_UP_DIGITIZER: +- switch (usage->hid) { +- /* we do not want to map these: no input-oriented meaning */ +- case 0x14: +- case 0x23: +- case HID_DG_INPUTMODE: +- case HID_DG_DEVICEINDEX: +- case HID_DG_CONTACTCOUNT: +- case HID_DG_CONTACTMAX: +- case HID_DG_INRANGE: +- case HID_DG_CONFIDENCE: +- return -1; +- case HID_DG_TIPSWITCH: +- /* touchscreen emulation */ +- hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); +- input_set_capability(hi->input, EV_KEY, BTN_TOUCH); +- return 1; +- case HID_DG_WIDTH: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_TOUCH_MAJOR); +- input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, +- f1, f2, df / SN_WIDTH, 0); +- return 1; +- case HID_DG_HEIGHT: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_TOUCH_MINOR); +- input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, +- f1, f2, df / SN_WIDTH, 0); +- input_set_abs_params(hi->input, ABS_MT_ORIENTATION, +- 0, 1, 0, 0); +- return 1; +- case HID_DG_CONTACTID: +- input_mt_init_slots(hi->input, MAX_SLOTS); +- return 1; +- } +- /* let hid-input decide for the others */ +- return 0; +- +- case 0xff000000: +- /* we do not want to map these: no input-oriented meaning */ +- return -1; +- } +- +- return 0; +-} +- +-static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- /* tell hid-input to skip setup of these event types */ +- if (usage->type == EV_KEY || usage->type == EV_ABS) +- set_bit(usage->type, hi->input->evbit); +- return -1; +-} +- +-/* +- * this function is called when a whole packet has been received and processed, +- * so that it can decide what to send to the input layer. +- */ +-static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) +-{ +- int i; +- for (i = 0; i < MAX_SLOTS; ++i) { +- struct mmm_finger *f = &md->f[i]; +- if (!f->valid) { +- /* this finger is just placeholder data, ignore */ +- continue; +- } +- input_mt_slot(input, i); +- input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch); +- if (f->touch) { +- /* this finger is on the screen */ +- int wide = (f->w > f->h); +- /* divided by two to match visual scale of touch */ +- int major = max(f->w, f->h) >> 1; +- int minor = min(f->w, f->h) >> 1; +- +- input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); +- input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); +- input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); +- input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); +- input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); +- } +- f->valid = 0; +- } +- +- input_mt_report_pointer_emulation(input, true); +- input_sync(input); +-} +- +-/* +- * this function is called upon all reports +- * so that we can accumulate contact point information, +- * and call input_mt_sync after each point. +- */ +-static int mmm_event(struct hid_device *hid, struct hid_field *field, +- struct hid_usage *usage, __s32 value) +-{ +- struct mmm_data *md = hid_get_drvdata(hid); +- /* +- * strangely, this function can be called before +- * field->hidinput is initialized! +- */ +- if (hid->claimed & HID_CLAIMED_INPUT) { +- struct input_dev *input = field->hidinput->input; +- switch (usage->hid) { +- case HID_DG_TIPSWITCH: +- md->touch = value; +- break; +- case HID_DG_CONFIDENCE: +- md->valid = value; +- break; +- case HID_DG_WIDTH: +- if (md->valid) +- md->f[md->curid].w = value; +- break; +- case HID_DG_HEIGHT: +- if (md->valid) +- md->f[md->curid].h = value; +- break; +- case HID_DG_CONTACTID: +- value = clamp_val(value, 0, MAX_SLOTS - 1); +- if (md->valid) { +- md->curid = value; +- md->f[value].touch = md->touch; +- md->f[value].valid = 1; +- md->nreal++; +- } +- break; +- case HID_GD_X: +- if (md->valid) +- md->f[md->curid].x = value; +- break; +- case HID_GD_Y: +- if (md->valid) +- md->f[md->curid].y = value; +- break; +- case HID_DG_CONTACTCOUNT: +- if (value) +- md->nexp = value; +- if (md->nreal >= md->nexp) { +- mmm_filter_event(md, input); +- md->nreal = 0; +- } +- break; +- } +- } +- +- /* we have handled the hidinput part, now remains hiddev */ +- if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) +- hid->hiddev_hid_event(hid, field, usage, value); +- +- return 1; +-} +- +-static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id) +-{ +- int ret; +- struct mmm_data *md; +- +- hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; +- +- md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); +- if (!md) { +- hid_err(hdev, "cannot allocate 3M data\n"); +- return -ENOMEM; +- } +- hid_set_drvdata(hdev, md); +- +- ret = hid_parse(hdev); +- if (!ret) +- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); +- +- if (ret) +- kfree(md); +- return ret; +-} +- +-static void mmm_remove(struct hid_device *hdev) +-{ +- hid_hw_stop(hdev); +- kfree(hid_get_drvdata(hdev)); +- hid_set_drvdata(hdev, NULL); +-} +- +-static const struct hid_device_id mmm_devices[] = { +- { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, +- { } +-}; +-MODULE_DEVICE_TABLE(hid, mmm_devices); +- +-static const struct hid_usage_id mmm_grabbed_usages[] = { +- { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, +- { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} +-}; +- +-static struct hid_driver mmm_driver = { +- .name = "3m-pct", +- .id_table = mmm_devices, +- .probe = mmm_probe, +- .remove = mmm_remove, +- .input_mapping = mmm_input_mapping, +- .input_mapped = mmm_input_mapped, +- .usage_table = mmm_grabbed_usages, +- .event = mmm_event, +-}; +- +-static int __init mmm_init(void) +-{ +- return hid_register_driver(&mmm_driver); +-} +- +-static void __exit mmm_exit(void) +-{ +- hid_unregister_driver(&mmm_driver); +-} +- +-module_init(mmm_init); +-module_exit(mmm_exit); +- +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index d31301e..0175f85 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -11,6 +11,12 @@ + * Copyright (c) 2010 Henrik Rydberg + * Copyright (c) 2010 Canonical, Ltd. + * ++ * This code is partly based on hid-3m-pct.c: ++ * ++ * Copyright (c) 2009-2010 Stephane Chatty ++ * Copyright (c) 2010 Henrik Rydberg ++ * Copyright (c) 2010 Canonical, Ltd. ++ * + */ + + /* +@@ -69,6 +75,8 @@ struct mt_class { + __s32 name; /* MT_CLS */ + __s32 quirks; + __s32 sn_move; /* Signal/noise ratio for move events */ ++ __s32 sn_width; /* Signal/noise ratio for width events */ ++ __s32 sn_height; /* Signal/noise ratio for height events */ + __s32 sn_pressure; /* Signal/noise ratio for pressure events */ + __u8 maxcontacts; + }; +@@ -80,6 +88,7 @@ struct mt_class { + #define MT_CLS_CYPRESS 4 + #define MT_CLS_EGALAX 5 + #define MT_CLS_STANTUM 6 ++#define MT_CLS_3M 7 + + #define MT_DEFAULT_MAXCONTACT 10 + +@@ -141,6 +150,12 @@ struct mt_class mt_classes[] = { + }, + { .name = MT_CLS_STANTUM, + .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, ++ { .name = MT_CLS_3M, ++ .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | ++ MT_QUIRK_SLOT_IS_CONTACTID, ++ .sn_move = 2048, ++ .sn_width = 128, ++ .sn_height = 128 }, + + { } + }; +@@ -230,11 +245,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + case HID_DG_WIDTH: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TOUCH_MAJOR); ++ set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, ++ cls->sn_width); + td->last_slot_field = usage->hid; + return 1; + case HID_DG_HEIGHT: + hid_map_usage(hi, usage, bit, max, + EV_ABS, ABS_MT_TOUCH_MINOR); ++ set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, ++ cls->sn_height); + input_set_abs_params(hi->input, + ABS_MT_ORIENTATION, 0, 1, 0, 0); + td->last_slot_field = usage->hid; +@@ -332,11 +351,18 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) + input_mt_report_slot_state(input, MT_TOOL_FINGER, + s->touch_state); + if (s->touch_state) { ++ /* this finger is on the screen */ ++ int wide = (s->w > s->h); ++ /* divided by two to match visual scale of touch */ ++ int major = max(s->w, s->h) >> 1; ++ int minor = min(s->w, s->h) >> 1; ++ + input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); + input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); ++ input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); + input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); +- input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w); +- input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h); ++ input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); ++ input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); + } + s->seen_in_this_frame = false; + +@@ -398,6 +424,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, + break; + + default: ++ if (td->last_field_index ++ && field->index == td->last_field_index) ++ /* we reach here when the last field in the ++ * report is not related to multitouch. ++ * This is not good. As a temporary solution, ++ * we trigger our mt event completion and ++ * ignore the field. ++ */ ++ break; + /* fallback to the generic hidinput handling */ + return 0; + } +@@ -513,6 +548,14 @@ static void mt_remove(struct hid_device *hdev) + + static const struct hid_device_id mt_devices[] = { + ++ /* 3M panels */ ++ { .driver_data = MT_CLS_3M, ++ HID_USB_DEVICE(USB_VENDOR_ID_3M, ++ USB_DEVICE_ID_3M1968) }, ++ { .driver_data = MT_CLS_3M, ++ HID_USB_DEVICE(USB_VENDOR_ID_3M, ++ USB_DEVICE_ID_3M2256) }, ++ + /* Cando panels */ + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, + HID_USB_DEVICE(USB_VENDOR_ID_CANDO, +commit 2955caed8b9865c1f04fcde6bd7103d5d5ec9415 +Author: Benjamin Tissoires +Date: Thu Apr 21 14:15:59 2011 +0200 + + HID: hid-multitouch: refactor last_field_index + + the current implementation requires the devices to report + HID_DG_CONTACTCOUNT to set the last_field_index value. + However, devices reporting in serial mode (DWAV and PenMount) + do not send this field. + Other devices (3M) add other fields in the reports descriptor + that are not multitouch related at the end, thus the need to + add a special case in the default case when handling events. + + A first work around has been set up but with PenMount devices, + we have reached the limit. + + The idea is to calculate the last_field_index by relying only on + multitouch fields the device send. This allows us to remove + the handling of non-multitouch events in hid-multitouch, and + guarantee that the function mt_emit_event is always called. + + Signed-off-by: Benjamin Tissoires + Reviewed-and-tested-by: Henrik Rydberg + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 0175f85..6005e78 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -210,6 +210,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + /* touchscreen emulation */ + set_abs(hi->input, ABS_X, field, cls->sn_move); + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_GD_Y: + if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) +@@ -221,6 +222,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + /* touchscreen emulation */ + set_abs(hi->input, ABS_Y, field, cls->sn_move); + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + } + return 0; +@@ -229,18 +231,22 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + switch (usage->hid) { + case HID_DG_INRANGE: + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_DG_CONFIDENCE: + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_DG_TIPSWITCH: + hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); + input_set_capability(hi->input, EV_KEY, BTN_TOUCH); + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_DG_CONTACTID: + input_mt_init_slots(hi->input, td->maxcontacts); + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_DG_WIDTH: + hid_map_usage(hi, usage, bit, max, +@@ -248,6 +254,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, + cls->sn_width); + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_DG_HEIGHT: + hid_map_usage(hi, usage, bit, max, +@@ -257,6 +264,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + input_set_abs_params(hi->input, + ABS_MT_ORIENTATION, 0, 1, 0, 0); + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_DG_TIPPRESSURE: + if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) +@@ -269,13 +277,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, + set_abs(hi->input, ABS_PRESSURE, field, + cls->sn_pressure); + td->last_slot_field = usage->hid; ++ td->last_field_index = field->index; + return 1; + case HID_DG_CONTACTCOUNT: +- td->last_field_index = field->report->maxfield - 1; ++ td->last_field_index = field->index; + return 1; + case HID_DG_CONTACTMAX: + /* we don't set td->last_slot_field as contactcount and + * contact max are global to the report */ ++ td->last_field_index = field->index; + return -1; + } + /* let hid-input decide for the others */ +@@ -424,23 +434,12 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, + break; + + default: +- if (td->last_field_index +- && field->index == td->last_field_index) +- /* we reach here when the last field in the +- * report is not related to multitouch. +- * This is not good. As a temporary solution, +- * we trigger our mt event completion and +- * ignore the field. +- */ +- break; + /* fallback to the generic hidinput handling */ + return 0; + } + + if (usage->hid == td->last_slot_field) { + mt_complete_slot(td); +- if (!td->last_field_index) +- mt_emit_event(td, field->hidinput->input); + } + + if (field->index == td->last_field_index +commit 6ab3a9a63fc16b04f7de48eb0190d516dd7574df +Author: John Sung +Date: Thu Apr 21 16:21:52 2011 +0200 + + HID: hid-multitouch: add support for PenMount dual-touch panel + + This patch adds PenMount support to hid-multitouch. A new class + MT_CLS_CONFIDENCE is defined for PenMount, since it uses HID_DG_CONFIDENCE as + the valid flag. + + Signed-off-by: John Sung + [benjamin.tissoires@enac.fr: rebased on top of last_index_field changes] + Signed-off-by: Benjamin Tissoires + Acked-by: Henrik Rydberg + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 996ae3a..8058cf1 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -313,6 +313,7 @@ config HID_MULTITOUCH + - Cypress TrueTouch panels + - Hanvon dual touch panels + - IrTouch Infrared USB panels ++ - PenMount dual touch panels + - Pixcir dual touch panels + - 'Sensing Win7-TwoFinger' panel by GeneralTouch + - eGalax dual-touch panels, including the +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index c3d6626..6e31b9f 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1438,6 +1438,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index d485894..252aeba 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -484,6 +484,9 @@ + #define USB_VENDOR_ID_PANTHERLORD 0x0810 + #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 + ++#define USB_VENDOR_ID_PENMOUNT 0x14e1 ++#define USB_DEVICE_ID_PENMOUNT_PCI 0x3500 ++ + #define USB_VENDOR_ID_PETALYNX 0x18b1 + #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 6005e78..51b5d27 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -89,6 +89,7 @@ struct mt_class { + #define MT_CLS_EGALAX 5 + #define MT_CLS_STANTUM 6 + #define MT_CLS_3M 7 ++#define MT_CLS_CONFIDENCE 8 + + #define MT_DEFAULT_MAXCONTACT 10 + +@@ -156,6 +157,8 @@ struct mt_class mt_classes[] = { + .sn_move = 2048, + .sn_width = 128, + .sn_height = 128 }, ++ { .name = MT_CLS_CONFIDENCE, ++ .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, + + { } + }; +@@ -584,6 +587,11 @@ static const struct hid_device_id mt_devices[] = { + HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, + USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, + ++ /* PenMount panels */ ++ { .driver_data = MT_CLS_CONFIDENCE, ++ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, ++ USB_DEVICE_ID_PENMOUNT_PCI) }, ++ + /* PixCir-based panels */ + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, + HID_USB_DEVICE(USB_VENDOR_ID_HANVON, +commit 4a6ee685fbcba4a440cf86f41557752ba81e2ccf +Author: Benjamin Tissoires +Date: Fri Apr 22 11:51:48 2011 +0200 + + HID: hid-multitouch: merge hid-mosart into hid-multitouch + + This patch include MosArt devices into hid-multitouch. + MosArt devices now support mt-protocol B. + + We also need to introduce a new quirk for mosart devices to support + their contactID. + + Signed-off-by: Benjamin Tissoires + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 8058cf1..d2d4e5f 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -288,12 +288,6 @@ config HID_MICROSOFT + ---help--- + Support for Microsoft devices that are not fully compliant with HID standard. + +-config HID_MOSART +- tristate "MosArt dual-touch panels" +- depends on USB_HID +- ---help--- +- Support for MosArt dual-touch panels. +- + config HID_MONTEREY + tristate "Monterey Genius KB29E keyboard" if EXPERT + depends on USB_HID +@@ -313,6 +307,7 @@ config HID_MULTITOUCH + - Cypress TrueTouch panels + - Hanvon dual touch panels + - IrTouch Infrared USB panels ++ - MosArt dual-touch panels + - PenMount dual touch panels + - Pixcir dual touch panels + - 'Sensing Win7-TwoFinger' panel by GeneralTouch +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index 11c9f0b..f8cc4ea 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -45,7 +45,6 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o + obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o + obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o + obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o +-obj-$(CONFIG_HID_MOSART) += hid-mosart.o + obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o + obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o + obj-$(CONFIG_HID_ORTEK) += hid-ortek.o +diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c +deleted file mode 100644 +index aed7ffe..0000000 +--- a/drivers/hid/hid-mosart.c ++++ /dev/null +@@ -1,296 +0,0 @@ +-/* +- * HID driver for the multitouch panel on the ASUS EeePC T91MT +- * +- * Copyright (c) 2009-2010 Stephane Chatty +- * Copyright (c) 2010 Teemu Tuominen +- * +- */ +- +-/* +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the Free +- * Software Foundation; either version 2 of the License, or (at your option) +- * any later version. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include "usbhid/usbhid.h" +- +-MODULE_AUTHOR("Stephane Chatty "); +-MODULE_DESCRIPTION("MosArt dual-touch panel"); +-MODULE_LICENSE("GPL"); +- +-#include "hid-ids.h" +- +-struct mosart_data { +- __u16 x, y; +- __u8 id; +- bool valid; /* valid finger data, or just placeholder? */ +- bool first; /* is this the first finger in this frame? */ +- bool activity_now; /* at least one active finger in this frame? */ +- bool activity; /* at least one active finger previously? */ +-}; +- +-static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- switch (usage->hid & HID_USAGE_PAGE) { +- +- case HID_UP_GENDESK: +- switch (usage->hid) { +- case HID_GD_X: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_X); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_X, +- field->logical_minimum, +- field->logical_maximum, 0, 0); +- return 1; +- case HID_GD_Y: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_POSITION_Y); +- /* touchscreen emulation */ +- input_set_abs_params(hi->input, ABS_Y, +- field->logical_minimum, +- field->logical_maximum, 0, 0); +- return 1; +- } +- return 0; +- +- case HID_UP_DIGITIZER: +- switch (usage->hid) { +- case HID_DG_CONFIDENCE: +- case HID_DG_TIPSWITCH: +- case HID_DG_INPUTMODE: +- case HID_DG_DEVICEINDEX: +- case HID_DG_CONTACTCOUNT: +- case HID_DG_CONTACTMAX: +- case HID_DG_TIPPRESSURE: +- case HID_DG_WIDTH: +- case HID_DG_HEIGHT: +- return -1; +- case HID_DG_INRANGE: +- /* touchscreen emulation */ +- hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); +- return 1; +- +- case HID_DG_CONTACTID: +- hid_map_usage(hi, usage, bit, max, +- EV_ABS, ABS_MT_TRACKING_ID); +- return 1; +- +- } +- return 0; +- +- case 0xff000000: +- /* ignore HID features */ +- return -1; +- +- case HID_UP_BUTTON: +- /* ignore buttons */ +- return -1; +- } +- +- return 0; +-} +- +-static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- if (usage->type == EV_KEY || usage->type == EV_ABS) +- clear_bit(usage->code, *bit); +- +- return 0; +-} +- +-/* +- * this function is called when a whole finger has been parsed, +- * so that it can decide what to send to the input layer. +- */ +-static void mosart_filter_event(struct mosart_data *td, struct input_dev *input) +-{ +- td->first = !td->first; /* touchscreen emulation */ +- +- if (!td->valid) { +- /* +- * touchscreen emulation: if no finger in this frame is valid +- * and there previously was finger activity, this is a release +- */ +- if (!td->first && !td->activity_now && td->activity) { +- input_event(input, EV_KEY, BTN_TOUCH, 0); +- td->activity = false; +- } +- return; +- } +- +- input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); +- input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); +- input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); +- +- input_mt_sync(input); +- td->valid = false; +- +- /* touchscreen emulation: if first active finger in this frame... */ +- if (!td->activity_now) { +- /* if there was no previous activity, emit touch event */ +- if (!td->activity) { +- input_event(input, EV_KEY, BTN_TOUCH, 1); +- td->activity = true; +- } +- td->activity_now = true; +- /* and in any case this is our preferred finger */ +- input_event(input, EV_ABS, ABS_X, td->x); +- input_event(input, EV_ABS, ABS_Y, td->y); +- } +-} +- +- +-static int mosart_event(struct hid_device *hid, struct hid_field *field, +- struct hid_usage *usage, __s32 value) +-{ +- struct mosart_data *td = hid_get_drvdata(hid); +- +- if (hid->claimed & HID_CLAIMED_INPUT) { +- struct input_dev *input = field->hidinput->input; +- switch (usage->hid) { +- case HID_DG_INRANGE: +- td->valid = !!value; +- break; +- case HID_GD_X: +- td->x = value; +- break; +- case HID_GD_Y: +- td->y = value; +- mosart_filter_event(td, input); +- break; +- case HID_DG_CONTACTID: +- td->id = value; +- break; +- case HID_DG_CONTACTCOUNT: +- /* touch emulation: this is the last field in a frame */ +- td->first = false; +- td->activity_now = false; +- break; +- case HID_DG_CONFIDENCE: +- case HID_DG_TIPSWITCH: +- /* avoid interference from generic hidinput handling */ +- break; +- +- default: +- /* fallback to the generic hidinput handling */ +- return 0; +- } +- } +- +- /* we have handled the hidinput part, now remains hiddev */ +- if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) +- hid->hiddev_hid_event(hid, field, usage, value); +- +- return 1; +-} +- +-static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id) +-{ +- int ret; +- struct mosart_data *td; +- +- +- td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL); +- if (!td) { +- hid_err(hdev, "cannot allocate MosArt data\n"); +- return -ENOMEM; +- } +- td->valid = false; +- td->activity = false; +- td->activity_now = false; +- td->first = false; +- hid_set_drvdata(hdev, td); +- +- /* currently, it's better to have one evdev device only */ +-#if 0 +- hdev->quirks |= HID_QUIRK_MULTI_INPUT; +-#endif +- +- ret = hid_parse(hdev); +- if (ret == 0) +- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); +- +- if (ret == 0) { +- struct hid_report_enum *re = hdev->report_enum +- + HID_FEATURE_REPORT; +- struct hid_report *r = re->report_id_hash[7]; +- +- r->field[0]->value[0] = 0x02; +- usbhid_submit_report(hdev, r, USB_DIR_OUT); +- } else +- kfree(td); +- +- return ret; +-} +- +-#ifdef CONFIG_PM +-static int mosart_reset_resume(struct hid_device *hdev) +-{ +- struct hid_report_enum *re = hdev->report_enum +- + HID_FEATURE_REPORT; +- struct hid_report *r = re->report_id_hash[7]; +- +- r->field[0]->value[0] = 0x02; +- usbhid_submit_report(hdev, r, USB_DIR_OUT); +- return 0; +-} +-#endif +- +-static void mosart_remove(struct hid_device *hdev) +-{ +- hid_hw_stop(hdev); +- kfree(hid_get_drvdata(hdev)); +- hid_set_drvdata(hdev, NULL); +-} +- +-static const struct hid_device_id mosart_devices[] = { +- { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, +- { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, +- { } +-}; +-MODULE_DEVICE_TABLE(hid, mosart_devices); +- +-static const struct hid_usage_id mosart_grabbed_usages[] = { +- { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, +- { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} +-}; +- +-static struct hid_driver mosart_driver = { +- .name = "mosart", +- .id_table = mosart_devices, +- .probe = mosart_probe, +- .remove = mosart_remove, +- .input_mapping = mosart_input_mapping, +- .input_mapped = mosart_input_mapped, +- .usage_table = mosart_grabbed_usages, +- .event = mosart_event, +-#ifdef CONFIG_PM +- .reset_resume = mosart_reset_resume, +-#endif +-}; +- +-static int __init mosart_init(void) +-{ +- return hid_register_driver(&mosart_driver); +-} +- +-static void __exit mosart_exit(void) +-{ +- hid_unregister_driver(&mosart_driver); +-} +- +-module_init(mosart_init); +-module_exit(mosart_exit); +- +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index 51b5d27..bf46804 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -50,6 +50,7 @@ MODULE_LICENSE("GPL"); + #define MT_QUIRK_VALID_IS_INRANGE (1 << 4) + #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5) + #define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 6) ++#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 7) + + struct mt_slot { + __s32 x, y, p, w, h; +@@ -90,6 +91,7 @@ struct mt_class { + #define MT_CLS_STANTUM 6 + #define MT_CLS_3M 7 + #define MT_CLS_CONFIDENCE 8 ++#define MT_CLS_CONFIDENCE_MINUS_ONE 9 + + #define MT_DEFAULT_MAXCONTACT 10 + +@@ -140,7 +142,9 @@ struct mt_class mt_classes[] = { + .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | + MT_QUIRK_CYPRESS, + .maxcontacts = 10 }, +- ++ { .name = MT_CLS_CONFIDENCE_MINUS_ONE, ++ .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | ++ MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, + { .name = MT_CLS_EGALAX, + .quirks = MT_QUIRK_SLOT_IS_CONTACTID | + MT_QUIRK_VALID_IS_INRANGE | +@@ -325,6 +329,9 @@ static int mt_compute_slot(struct mt_device *td) + if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER) + return td->num_received; + ++ if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE) ++ return td->curdata.contactid - 1; ++ + return find_slot_from_contactid(td); + } + +@@ -587,6 +594,17 @@ static const struct hid_device_id mt_devices[] = { + HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, + USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, + ++ /* MosArt panels */ ++ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, ++ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, ++ USB_DEVICE_ID_ASUS_T91MT)}, ++ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, ++ HID_USB_DEVICE(USB_VENDOR_ID_ASUS, ++ USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, ++ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, ++ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, ++ USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, ++ + /* PenMount panels */ + { .driver_data = MT_CLS_CONFIDENCE, + HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, +commit 4e61f0d75aa86c9e59451f6bcffcdceb355b4fc4 +Author: Austin Zhang +Date: Mon May 9 23:54:14 2011 +0800 + + HID: hid-multitouch: add support for Ilitek dual-touch panel + + Added ILITEK hid dual touch panel support into hid-multitouch. + + Signed-off-by: Austin Zhang + Reviewed-by: Benjamin Tissoires + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index d2d4e5f..d9635d6 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -306,6 +306,7 @@ config HID_MULTITOUCH + - Cando dual touch panel + - Cypress TrueTouch panels + - Hanvon dual touch panels ++ - Ilitek dual touch panel + - IrTouch Infrared USB panels + - MosArt dual-touch panels + - PenMount dual touch panels +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 6e31b9f..c0ea857 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1377,6 +1377,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 252aeba..0f29b3f 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -330,6 +330,9 @@ + #define USB_DEVICE_ID_UGCI_FLYING 0x0020 + #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 + ++#define USB_VENDOR_ID_ILITEK 0x222a ++#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 ++ + #define USB_VENDOR_ID_IMATION 0x0718 + #define USB_DEVICE_ID_DISC_STAKKA 0xd000 + +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index bf46804..b21251b 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -589,6 +589,11 @@ static const struct hid_device_id mt_devices[] = { + HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, + USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, + ++ /* Ilitek dual touch panel */ ++ { .driver_data = MT_CLS_DEFAULT, ++ HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, ++ USB_DEVICE_ID_ILITEK_MULTITOUCH) }, ++ + /* IRTOUCH panels */ + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, + HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, +commit df167c4a0d68a9dbde044a39a77f255ac666f93e +Author: Benjamin Tissoires +Date: Wed May 18 15:27:24 2011 +0200 + + HID: hid-multitouch: Add support for Lumio panels + + This patch enables support for Lumio optical devices. + + Signed-off-by: Benjamin Tissoires + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index d9635d6..5a54b13 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -308,6 +308,7 @@ config HID_MULTITOUCH + - Hanvon dual touch panels + - Ilitek dual touch panel + - IrTouch Infrared USB panels ++ - Lumio CrystalTouch panels + - MosArt dual-touch panels + - PenMount dual touch panels + - Pixcir dual touch panels +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index c0ea857..3dad069 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1410,6 +1410,7 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 0f29b3f..bfbc0d2 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -410,6 +410,9 @@ + #define USB_DEVICE_ID_DINOVO_MINI 0xc71f + #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03 + ++#define USB_VENDOR_ID_LUMIO 0x202e ++#define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 ++ + #define USB_VENDOR_ID_MCC 0x09db + #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 + #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index b21251b..ef33e2d 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -599,6 +599,11 @@ static const struct hid_device_id mt_devices[] = { + HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, + USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, + ++ /* Lumio panels */ ++ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, ++ HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, ++ USB_DEVICE_ID_CRYSTALTOUCH) }, ++ + /* MosArt panels */ + { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, + HID_USB_DEVICE(USB_VENDOR_ID_ASUS, +commit c04abeeff9d76a703cac1e6d312853b0fc8136f5 +Author: Benjamin Tissoires +Date: Thu May 19 11:37:29 2011 +0200 + + HID: hid-multitouch: add support for Elo TouchSystems 2515 IntelliTouch Plus + + This patch adds support for Elo TouchSystems 2515 IntelliTouch Plus + that can be found in Lenovo A700 all-in-one. + + Signed-off-by: Benjamin Tissoires + Tested-by: Bastien Nocera + Signed-off-by: Jiri Kosina + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 5a54b13..1572ff1 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -305,6 +305,7 @@ config HID_MULTITOUCH + - 3M PCT touch screens + - Cando dual touch panel - Cypress TrueTouch panels + - Elo TouchSystems IntelliTouch Plus panels - Hanvon dual touch panels - - Pixcir dual touch panels - - 'Sensing Win7-TwoFinger' panel by GeneralTouch + - Ilitek dual touch panel + - IrTouch Infrared USB panels +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 3dad069..053fc08 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c -@@ -1335,6 +1335,7 @@ static const struct hid_device_id hid_have_special_driver[] = { +@@ -1366,6 +1366,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, @@ -32,9 +2207,11 @@ Signed-off-by: Jiri Kosina { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index bfbc0d2..6c19d1a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h -@@ -219,6 +219,7 @@ +@@ -216,6 +216,7 @@ #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 #define USB_VENDOR_ID_ELO 0x04E7 @@ -42,29 +2219,30 @@ Signed-off-by: Jiri Kosina #define USB_DEVICE_ID_ELO_TS2700 0x0020 #define USB_VENDOR_ID_EMS 0x2006 +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index ef33e2d..3bc8de6 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c -@@ -69,6 +69,7 @@ struct mt_class { - #define MT_CLS_DUAL1 2 - #define MT_CLS_DUAL2 3 - #define MT_CLS_CYPRESS 4 -+#define MT_CLS_DUAL_NSMU_CONTACTID 5 +@@ -92,6 +92,7 @@ struct mt_class { + #define MT_CLS_3M 7 + #define MT_CLS_CONFIDENCE 8 + #define MT_CLS_CONFIDENCE_MINUS_ONE 9 ++#define MT_CLS_DUAL_NSMU_CONTACTID 10 - /* - * these device-dependent functions determine what slot corresponds -@@ -119,6 +120,11 @@ struct mt_class mt_classes[] = { - MT_QUIRK_CYPRESS, - .maxcontacts = 10 }, + #define MT_DEFAULT_MAXCONTACT 10 +@@ -163,6 +164,10 @@ struct mt_class mt_classes[] = { + .sn_height = 128 }, + { .name = MT_CLS_CONFIDENCE, + .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, + { .name = MT_CLS_DUAL_NSMU_CONTACTID, + .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | + MT_QUIRK_SLOT_IS_CONTACTID, + .maxcontacts = 2 }, -+ + { } }; - -@@ -465,6 +471,11 @@ static const struct hid_device_id mt_devices[] = { +@@ -584,6 +589,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, @@ -74,5 +2252,5 @@ Signed-off-by: Jiri Kosina + USB_DEVICE_ID_ELO_TS2515) }, + /* GeneralTouch panel */ - { .driver_data = MT_CLS_DUAL2, + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, diff --git a/hid-ntrig-deref-unclaimed-input.patch b/hid-ntrig-deref-unclaimed-input.patch deleted file mode 100644 index 8719eae30..000000000 --- a/hid-ntrig-deref-unclaimed-input.patch +++ /dev/null @@ -1,46 +0,0 @@ -commit f41a52d3010579949a3b9fd76783120d9643b60b -Author: Rafi Rubin -Date: Tue Mar 8 00:24:29 2011 -0500 - - HID: ntrig don't dereference unclaimed hidinput - - Check before dereferencing field->hidinput to fix a reported invalid - deference bug. - - Signed-off-by: Rafi Rubin - Signed-off-by: Jiri Kosina - -diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c -index beb4034..a93e58c 100644 ---- a/drivers/hid/hid-ntrig.c -+++ b/drivers/hid/hid-ntrig.c -@@ -539,8 +539,19 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, - static int ntrig_event (struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) - { -- struct input_dev *input = field->hidinput->input; - struct ntrig_data *nd = hid_get_drvdata(hid); -+ struct input_dev *input; -+ -+ /* Skip processing if not a claimed input */ -+ if (!(hid->claimed & HID_CLAIMED_INPUT)) -+ goto not_claimed_input; -+ -+ /* This function is being called before the structures are fully -+ * initialized */ -+ if(!(field->hidinput && field->hidinput->input)) -+ return -EINVAL; -+ -+ input = field->hidinput->input; - - /* No special handling needed for the pen */ - if (field->application == HID_DG_PEN) -@@ -810,6 +821,8 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, - } - } - -+not_claimed_input: -+ - /* we have handled the hidinput part, now remains hiddev */ - if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); diff --git a/input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch b/input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch deleted file mode 100644 index f95908ed7..000000000 --- a/input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Manoj Iyer -Date: Fri, 1 Apr 2011 05:39:43 +0000 (-0700) -Subject: Input: wacom - add support for Lenovo tablet ID (0xE6) -X-Git-Tag: v2.6.39-rc2~4^2~1 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=26fcd2a7618db6c16be6aa3e56c0f3c25381e5a3 - -Input: wacom - add support for Lenovo tablet ID (0xE6) -[ 2.6.38 backport ] - -Signed-off-by: Manoj Iyer -Acked-by: Ping Cheng -Signed-off-by: Dmitry Torokhov ---- -RHBZ 708307 - -diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c -index c87d94f..08ba5ad 100644 ---- a/drivers/input/tablet/wacom_wac.c -+++ b/drivers/input/tablet/wacom_wac.c -@@ -1439,6 +1439,8 @@ static const struct wacom_features wacom_features_0xE2 = - { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; - static const struct wacom_features wacom_features_0xE3 = - { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; -+static const struct wacom_features wacom_features_0xE6 = -+ { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, 0, TABLETPC2FG }; - static const struct wacom_features wacom_features_0x47 = - { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; - static struct wacom_features wacom_features_0xD0 = -@@ -1561,6 +1564,7 @@ const struct usb_device_id wacom_ids[] = { - { USB_DEVICE_WACOM(0x9F) }, - { USB_DEVICE_WACOM(0xE2) }, - { USB_DEVICE_WACOM(0xE3) }, -+ { USB_DEVICE_WACOM(0xE6) }, - { USB_DEVICE_WACOM(0x47) }, - { USB_DEVICE_LENOVO(0x6004) }, - { } diff --git a/intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch b/intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch deleted file mode 100644 index ec494f626..000000000 --- a/intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 8519dc4401ddf8a5399f979870bbeeadbc111186 Mon Sep 17 00:00:00 2001 -From: Mike Habeck -Date: Sat, 28 May 2011 13:15:07 -0500 -Subject: intel-iommu: Add domain check in domain_remove_one_dev_info - -From: Mike Habeck - -commit 8519dc4401ddf8a5399f979870bbeeadbc111186 upstream. - -The comment in domain_remove_one_dev_info() states "No need to compare -PCI domain; it has to be the same". But for the si_domain that isn't -going to be true, as it consists of all the PCI devices that are -identity mapped thus multiple PCI domains can be in si_domain. The -code needs to validate the PCI domain too. - -Signed-off-by: Mike Habeck -Signed-off-by: Mike Travis -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/intel-iommu.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c -@@ -3398,8 +3398,8 @@ static void domain_remove_one_dev_info(s - spin_lock_irqsave(&device_domain_lock, flags); - list_for_each_safe(entry, tmp, &domain->devices) { - info = list_entry(entry, struct device_domain_info, link); -- /* No need to compare PCI domain; it has to be the same */ -- if (info->bus == pdev->bus->number && -+ if (info->segment == pci_domain_nr(pdev->bus) && -+ info->bus == pdev->bus->number && - info->devfn == pdev->devfn) { - list_del(&info->link); - list_del(&info->global); diff --git a/intel-iommu-check-for-identity-mapping-candidate-using.patch b/intel-iommu-check-for-identity-mapping-candidate-using.patch deleted file mode 100644 index 50da53318..000000000 --- a/intel-iommu-check-for-identity-mapping-candidate-using.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 8fcc5372fbac085199d84a880503ed67aba3fe49 Mon Sep 17 00:00:00 2001 -From: Chris Wright -Date: Sat, 28 May 2011 13:15:02 -0500 -Subject: intel-iommu: Check for identity mapping candidate using - system dma mask - -From: Chris Wright - -commit 8fcc5372fbac085199d84a880503ed67aba3fe49 upstream. - -The identity mapping code appears to make the assumption that if the -devices dma_mask is greater than 32bits the device can use identity -mapping. But that is not true: take the case where we have a 40bit -device in a 44bit architecture. The device can potentially receive a -physical address that it will truncate and cause incorrect addresses -to be used. - -Instead check to see if the device's dma_mask is large enough -to address the system's dma_mask. - -Signed-off-by: Mike Travis -Reviewed-by: Mike Habeck -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/intel-iommu.c | 15 +++++++++++++-- - 1 file changed, 13 insertions(+), 2 deletions(-) - ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c -@@ -2190,8 +2190,19 @@ static int iommu_should_identity_map(str - * Assume that they will -- if they turn out not to be, then we can - * take them out of the 1:1 domain later. - */ -- if (!startup) -- return pdev->dma_mask > DMA_BIT_MASK(32); -+ if (!startup) { -+ /* -+ * If the device's dma_mask is less than the system's memory -+ * size then this is not a candidate for identity mapping. -+ */ -+ u64 dma_mask = pdev->dma_mask; -+ -+ if (pdev->dev.coherent_dma_mask && -+ pdev->dev.coherent_dma_mask < dma_mask) -+ dma_mask = pdev->dev.coherent_dma_mask; -+ -+ return dma_mask >= dma_get_required_mask(&pdev->dev); -+ } - - return 1; - } diff --git a/intel-iommu-dont-cache-iova-above-32bit.patch b/intel-iommu-dont-cache-iova-above-32bit.patch deleted file mode 100644 index 4a2691e63..000000000 --- a/intel-iommu-dont-cache-iova-above-32bit.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 1c9fc3d11b84fbd0c4f4aa7855702c2a1f098ebb Mon Sep 17 00:00:00 2001 -From: Chris Wright -Date: Sat, 28 May 2011 13:15:04 -0500 -Subject: intel-iommu: Dont cache iova above 32bit - -From: Chris Wright - -commit 1c9fc3d11b84fbd0c4f4aa7855702c2a1f098ebb upstream. - -Mike Travis and Mike Habeck reported an issue where iova allocation -would return a range that was larger than a device's dma mask. - -https://lkml.org/lkml/2011/3/29/423 - -The dmar initialization code will reserve all PCI MMIO regions and copy -those reservations into a domain specific iova tree. It is possible for -one of those regions to be above the dma mask of a device. It is typical -to allocate iovas with a 32bit mask (despite device's dma mask possibly -being larger) and cache the result until it exhausts the lower 32bit -address space. Freeing the iova range that is >= the last iova in the -lower 32bit range when there is still an iova above the 32bit range will -corrupt the cached iova by pointing it to a region that is above 32bit. -If that region is also larger than the device's dma mask, a subsequent -allocation will return an unusable iova and cause dma failure. - -Simply don't cache an iova that is above the 32bit caching boundary. - -Reported-by: Mike Travis -Reported-by: Mike Habeck -Acked-by: Mike Travis -Tested-by: Mike Habeck -Signed-off-by: Chris Wright -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/iova.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - ---- a/drivers/pci/iova.c -+++ b/drivers/pci/iova.c -@@ -63,8 +63,16 @@ __cached_rbnode_delete_update(struct iov - curr = iovad->cached32_node; - cached_iova = container_of(curr, struct iova, node); - -- if (free->pfn_lo >= cached_iova->pfn_lo) -- iovad->cached32_node = rb_next(&free->node); -+ if (free->pfn_lo >= cached_iova->pfn_lo) { -+ struct rb_node *node = rb_next(&free->node); -+ struct iova *iova = container_of(node, struct iova, node); -+ -+ /* only cache if it's below 32bit pfn */ -+ if (node && iova->pfn_lo < iovad->dma_32bit_pfn) -+ iovad->cached32_node = node; -+ else -+ iovad->cached32_node = NULL; -+ } - } - - /* Computes the padding size required, to make the diff --git a/intel-iommu-flush-unmaps-at-domain_exit.patch b/intel-iommu-flush-unmaps-at-domain_exit.patch deleted file mode 100644 index d08772a29..000000000 --- a/intel-iommu-flush-unmaps-at-domain_exit.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 7b668357810ecb5fdda4418689d50f5d95aea6a8 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 24 May 2011 12:02:41 +0100 -Subject: intel-iommu: Flush unmaps at domain_exit - -From: Alex Williamson - -commit 7b668357810ecb5fdda4418689d50f5d95aea6a8 upstream. - -We typically batch unmaps to be lazily flushed out at -regular intervals. When we destroy a domain, we need -to force a flush of these lazy unmaps to be sure none -reference the domain we're about to free. - -Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=35062 -Signed-off-by: Alex Williamson -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/intel-iommu.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c -@@ -1416,6 +1416,10 @@ static void domain_exit(struct dmar_doma - if (!domain) - return; - -+ /* Flush any lazy unmaps that may reference this domain */ -+ if (!intel_iommu_strict) -+ flush_unmaps_timeout(0); -+ - domain_remove_dev_info(domain); - /* destroy iovas */ - put_iova_domain(&domain->iovad); diff --git a/intel-iommu-only-unlink-device-domains-from-iommu.patch b/intel-iommu-only-unlink-device-domains-from-iommu.patch deleted file mode 100644 index 839c56496..000000000 --- a/intel-iommu-only-unlink-device-domains-from-iommu.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 9b4554b21ed07e8556405510638171f0c787742a Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 24 May 2011 12:19:04 -0400 -Subject: intel-iommu: Only unlink device domains from iommu - -From: Alex Williamson - -commit 9b4554b21ed07e8556405510638171f0c787742a upstream. - -Commit a97590e5 added unlinking domains from iommus to reciprocate the -iommu from domains unlinking that was already done. We actually want -to only do this for device domains and never for the static -identity map domain or VM domains. The SI domain is special and -never freed, while VM domain->id lives in their own special address -space, separate from iommu->domain_ids. - -In the current code, a VM can get domain->id zero, then mark that -domain unused when unbound from pci-stub. This leads to DMAR -write faults when the device is re-bound to the host driver. - -Signed-off-by: Alex Williamson -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/intel-iommu.c | 11 +++++++---- - 1 file changed, 7 insertions(+), 4 deletions(-) - ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c -@@ -3422,10 +3422,13 @@ static void domain_remove_one_dev_info(s - domain_update_iommu_cap(domain); - spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); - -- spin_lock_irqsave(&iommu->lock, tmp_flags); -- clear_bit(domain->id, iommu->domain_ids); -- iommu->domains[domain->id] = NULL; -- spin_unlock_irqrestore(&iommu->lock, tmp_flags); -+ if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && -+ !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) { -+ spin_lock_irqsave(&iommu->lock, tmp_flags); -+ clear_bit(domain->id, iommu->domain_ids); -+ iommu->domains[domain->id] = NULL; -+ spin_unlock_irqrestore(&iommu->lock, tmp_flags); -+ } - } - - spin_unlock_irqrestore(&device_domain_lock, flags); diff --git a/intel-iommu-remove-host-bridge-devices-from-identity.patch b/intel-iommu-remove-host-bridge-devices-from-identity.patch deleted file mode 100644 index 66cef4a52..000000000 --- a/intel-iommu-remove-host-bridge-devices-from-identity.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 825507d6d059f1cbe2503e0e5a3926225b983aec Mon Sep 17 00:00:00 2001 -From: Mike Travis -Date: Sat, 28 May 2011 13:15:06 -0500 -Subject: intel-iommu: Remove Host Bridge devices from identity - mapping - -From: Mike Travis - -commit 825507d6d059f1cbe2503e0e5a3926225b983aec upstream. - -When using the 1:1 (identity) PCI DMA remapping, PCI Host Bridge devices -that do not use the IOMMU causes a kernel panic. Fix that by not -inserting those devices into the si_domain. - -Signed-off-by: Mike Travis -Reviewed-by: Mike Habeck -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/intel-iommu.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c -@@ -46,6 +46,8 @@ - #define ROOT_SIZE VTD_PAGE_SIZE - #define CONTEXT_SIZE VTD_PAGE_SIZE - -+#define IS_BRIDGE_HOST_DEVICE(pdev) \ -+ ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST) - #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) - #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) - #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) -@@ -2217,6 +2219,9 @@ static int __init iommu_prepare_static_i - return -EFAULT; - - for_each_pci_dev(pdev) { -+ /* Skip Host/PCI Bridge devices */ -+ if (IS_BRIDGE_HOST_DEVICE(pdev)) -+ continue; - if (iommu_should_identity_map(pdev, 1)) { - printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n", - hw ? "hardware" : "software", pci_name(pdev)); diff --git a/intel-iommu-speed-up-processing-of-the-identity_mapping.patch b/intel-iommu-speed-up-processing-of-the-identity_mapping.patch deleted file mode 100644 index 9a2fd550e..000000000 --- a/intel-iommu-speed-up-processing-of-the-identity_mapping.patch +++ /dev/null @@ -1,43 +0,0 @@ -From cb452a4040bb051d92e85d6e7eb60c11734c1781 Mon Sep 17 00:00:00 2001 -From: Mike Travis -Date: Sat, 28 May 2011 13:15:03 -0500 -Subject: intel-iommu: Speed up processing of the identity_mapping - function - -From: Mike Travis - -commit cb452a4040bb051d92e85d6e7eb60c11734c1781 upstream. - -When there are a large count of PCI devices, and the pass through -option for iommu is set, much time is spent in the identity_mapping -function hunting though the iommu domains to check if a specific -device is "identity mapped". - -Speed up the function by checking the cached info to see if -it's mapped to the static identity domain. - -Signed-off-by: Mike Travis -Reviewed-by: Mike Habeck -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/intel-iommu.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c -@@ -2109,10 +2109,10 @@ static int identity_mapping(struct pci_d - if (likely(!iommu_identity_mapping)) - return 0; - -+ info = pdev->dev.archdata.iommu; -+ if (info && info != DUMMY_DEVICE_DOMAIN_INFO) -+ return (info->domain == si_domain); - -- list_for_each_entry(info, &si_domain->devices, link) -- if (info->dev == pdev) -- return 1; - return 0; - } - diff --git a/intel-iommu-use-coherent-dma-mask-when-requested.patch b/intel-iommu-use-coherent-dma-mask-when-requested.patch deleted file mode 100644 index 01b43db74..000000000 --- a/intel-iommu-use-coherent-dma-mask-when-requested.patch +++ /dev/null @@ -1,35 +0,0 @@ -From c681d0ba1252954208220ad32248a3e8e2fc98e4 Mon Sep 17 00:00:00 2001 -From: Mike Travis -Date: Sat, 28 May 2011 13:15:05 -0500 -Subject: intel-iommu: Use coherent DMA mask when requested - -From: Mike Travis - -commit c681d0ba1252954208220ad32248a3e8e2fc98e4 upstream. - -The __intel_map_single function is not honoring the passed in DMA mask. -This results in not using the coherent DMA mask when called from -intel_alloc_coherent(). - -Signed-off-by: Mike Travis -Acked-by: Chris Wright -Reviewed-by: Mike Habeck -Signed-off-by: David Woodhouse -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/pci/intel-iommu.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/pci/intel-iommu.c -+++ b/drivers/pci/intel-iommu.c -@@ -2606,8 +2606,7 @@ static dma_addr_t __intel_map_single(str - iommu = domain_get_iommu(domain); - size = aligned_nrpages(paddr, size); - -- iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), -- pdev->dma_mask); -+ iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask); - if (!iova) - goto error; - diff --git a/iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch b/iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch deleted file mode 100644 index 6743f9057..000000000 --- a/iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch +++ /dev/null @@ -1,103 +0,0 @@ -From sgruszka@redhat.com Mon Jun 20 10:09:55 2011 -From: Stanislaw Gruszka -To: kernel@lists.fedoraproject.org -Subject: [PATCH 2.6.38] iwlagn: use cts-to-self protection on 5000 adapters series -Date: Mon, 20 Jun 2011 16:11:22 +0200 -Message-Id: <1308579082-19006-2-git-send-email-sgruszka@redhat.com> - -This patch fixes 802.11n stability and performance regression we have -since 2.6.35. It boost performance on my 5GHz N-only network from about -5MB/s to 8MB/s. Similar percentage boost can be observed on 2.4 GHz. - -These are test results of 5x downloading of approximately 700MB iso -image: - -vanilla: 5.27 5.22 4.94 4.47 5.31 ; avr 5.0420 std 0.35110 -patched: 8.07 7.95 8.06 7.99 7.96 ; avr 8.0060 std 0.055946 - -This was achieved with NetworkManager configured to do not perform -periodical scans, by configuring constant BSSID. With periodical scans, -after some time, performance downgrade to unpatched driver level, like -in example below: - -patched: 7.40 7.61 4.28 4.37 4.80 avr 5.6920 std 1.6683 - -However patch still make better here, since similar test on unpatched -driver make link disconnects with below messages after some time: - -wlan1: authenticate with 00:23:69:35:d1:3f (try 1) -wlan1: authenticate with 00:23:69:35:d1:3f (try 2) -wlan1: authenticate with 00:23:69:35:d1:3f (try 3) -wlan1: authentication with 00:23:69:35:d1:3f timed out - -On 2.6.35 kernel patch helps against connection hangs with messages: - -iwlagn 0000:20:00.0: queue 10 stuck 3 time. Fw reload. -iwlagn 0000:20:00.0: On demand firmware reload -iwlagn 0000:20:00.0: Stopping AGG while state not ON or starting - -Signed-off-by: Stanislaw Gruszka ---- - drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - - drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 12 ++---------- - drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 8 ++++++++ - 3 files changed, 10 insertions(+), 11 deletions(-) - -diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c -index 537fb8c..909cc30 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-5000.c -+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c -@@ -517,7 +517,6 @@ static struct iwl_base_params iwl5000_base_params = { - }; - static struct iwl_ht_params iwl5000_ht_params = { - .ht_greenfield_support = true, -- .use_rts_for_aggregation = true, /* use rts/cts protection */ - }; - - #define IWL_DEVICE_5000 \ -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c -index 366340f..89762a7 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c -@@ -217,17 +217,9 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, - __le16 fc, __le32 *tx_flags) - { - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || -- info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { -+ info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || -+ info->flags & IEEE80211_TX_CTL_AMPDU) - *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; -- return; -- } -- -- if (priv->cfg->ht_params && -- priv->cfg->ht_params->use_rts_for_aggregation && -- info->flags & IEEE80211_TX_CTL_AMPDU) { -- *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; -- return; -- } - } - - /* Calc max signal level (dBm) among 3 possible receivers */ -diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -index ee802fe..b19fb85 100644 ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c -@@ -145,6 +145,14 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) - /* always get timestamp with Rx frame */ - ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; - -+ /* -+ * force CTS-to-self frames protection if RTS-CTS is not preferred -+ * one aggregation protection method -+ */ -+ if (!(priv->cfg->ht_params && -+ priv->cfg->ht_params->use_rts_for_aggregation)) -+ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; -+ - if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || - !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) - ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; --- -1.7.1 - diff --git a/kernel.spec b/kernel.spec index 5211df656..397f648c1 100644 --- a/kernel.spec +++ b/kernel.spec @@ -51,19 +51,19 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be prepended with "0.", so # for example a 3 here will become 0.3 # -%global baserelease 34 +%global baserelease 1 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base, # which yields a base_sublevel of 21. -%define base_sublevel 38 +%define base_sublevel 39 ## If this is a released kernel ## %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 8 +%define stable_update 2 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -596,8 +596,6 @@ Patch00: patch-2.6.%{base_sublevel}-git%{gitrev}.bz2 ### BRANCH PATCH ### %endif -Patch02: git-linus.diff - # we also need compile fixes for -vanilla Patch04: linux-2.6-compile-fixes.patch @@ -609,10 +607,7 @@ Patch05: linux-2.6-makefile-after_link.patch # revert upstream patches we get via other methods Patch09: linux-2.6-upstream-reverts.patch -# Git trees. -# Standalone patches -Patch20: linux-2.6-hotfixes.patch Patch29: linux-2.6-utrace-revert-make-ptrace-functions-static.patch Patch30: linux-2.6-tracehook.patch @@ -627,17 +622,14 @@ Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch Patch161: linux-2.6-i386-nx-emulation.patch -Patch200: linux-2.6-debug-sizeof-structs.patch Patch202: linux-2.6-debug-taint-vm.patch Patch203: linux-2.6-debug-vm-would-have-oomkilled.patch -Patch204: linux-2.6-debug-always-inline-kzalloc.patch Patch380: linux-2.6-defaults-pci_no_msi.patch Patch381: linux-2.6-defaults-pci_use_crs.patch # ASPM: enable powersave by default Patch383: linux-2.6-defaults-aspm.patch -Patch384: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch Patch385: pci-enable-aspm-state-clearing-regardless-of-policy.patch Patch389: ima-allow-it-to-be-completely-disabled-and-default-off.patch @@ -650,8 +642,6 @@ Patch394: linux-2.6-acpi-debug-infinite-loop.patch Patch450: linux-2.6-input-kill-stupid-messages.patch Patch452: linux-2.6.30-no-pcspkr-modalias.patch Patch453: revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch -Patch454: input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch -Patch455: hid-ntrig-deref-unclaimed-input.patch Patch456: hid-multitouch-add-support-for-elo-touchsystems.patch Patch460: linux-2.6-serial-460800.patch @@ -664,13 +654,9 @@ Patch570: linux-2.6-selinux-mprotect-checks.patch Patch580: linux-2.6-sparc-selinux-mprotect-checks.patch # scsi / block -Patch600: block-queue-refcount.patch -Patch601: block-export-blk_-get-put-_queue.patch -Patch602: block-blkdev_get-should-access-bd_disk-only-after.patch Patch603: cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch # libata -Patch620: ahci-add-another-pci-id-for-marvell.patch Patch621: libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch Patch650: hda_intel-prealloc-4mb-dmabuffer.patch @@ -689,35 +675,18 @@ Patch1555: fix_xen_guest_on_old_EC2.patch # nouveau + drm fixes Patch1809: drm-nouveau-fixes.patch Patch1810: drm-nouveau-updates.patch -Patch1811: drm-ttm-move-notify.patch Patch1819: drm-intel-big-hammer.patch # intel drm is all merged upstream -# fix for 945G corruption will hit stable eventually -Patch1821: drm-i915-fix-pipelined-fencing.patch Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open Patch1825: drm-intel-make-lvds-work.patch Patch1826: drm-intel-edp-fixes.patch -Patch1828: drm-intel-eeebox-eb1007-quirk.patch -Patch1829: drm-intel-restore-mode.patch Patch1830: drm-i915-snb-irq-stalls-fix.patch Patch1831: drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch # radeon - new hw + fixes for fusion and t500 regression Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -Patch1840: drm-radeon-update.patch -Patch1841: drm-radeon-update2.patch -Patch1842: drm-radeon-pageflip-oops-fix.patch -Patch1843: drm-radeon-update3.patch Patch1900: linux-2.6-intel-iommu-igfx.patch -Patch1901: intel-iommu-flush-unmaps-at-domain_exit.patch -Patch1902: intel-iommu-only-unlink-device-domains-from-iommu.patch -Patch1903: intel-iommu-check-for-identity-mapping-candidate-using.patch -Patch1904: intel-iommu-speed-up-processing-of-the-identity_mapping.patch -Patch1905: intel-iommu-dont-cache-iova-above-32bit.patch -Patch1906: intel-iommu-use-coherent-dma-mask-when-requested.patch -Patch1907: intel-iommu-remove-host-bridge-devices-from-identity.patch -Patch1908: intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch # linux1394 git patches Patch2200: linux-2.6-firewire-git-update.patch @@ -728,7 +697,6 @@ Patch2201: linux-2.6-firewire-git-pending.patch Patch2802: linux-2.6-silence-acpi-blacklist.patch # media patches -Patch2898: cx88-Fix-HVR4000-IR-keymap.patch Patch2899: linux-2.6-v4l-dvb-fixes.patch Patch2900: linux-2.6-v4l-dvb-update.patch Patch2901: linux-2.6-v4l-dvb-experimental.patch @@ -745,38 +713,21 @@ Patch12016: disable-i8042-check-on-apple-mac.patch Patch12018: neuter_intel_microcode_load.patch -Patch12101: apple_backlight.patch -Patch12102: efifb_update.patch -Patch12200: acpi_reboot.patch - # Runtime power management Patch12203: linux-2.6-usb-pci-autosuspend.patch Patch12204: linux-2.6-enable-more-pci-autosuspend.patch Patch12303: dmar-disable-when-ricoh-multifunction.patch -Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch Patch12306: scsi-sd-downgrade-caching-printk-from-error-to-notice.patch -#netconsole fixes -Patch12400: linux-2.6-netconsole-deadlock.patch - -# CVE-2011-1581 -Patch12402: bonding-incorrect-tx-queue-offset.patch - -# Restore reliable stack backtraces, and hopefully fix RHBZ #700718 -Patch12403: x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch - # Fix breakage of PCI network adapter names on older Dell systems Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch -Patch12407: scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch - Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch Patch12418: ath5k-disable-fast-channel-switching-by-default.patch -Patch12419: iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch Patch12420: crypto-aesni_intel-merge-with-fpu_ko.patch @@ -1203,8 +1154,6 @@ do done %endif -ApplyOptionalPatch git-linus.diff - ApplyPatch linux-2.6-makefile-after_link.patch # @@ -1217,9 +1166,7 @@ ApplyOptionalPatch linux-2.6-compile-fixes.patch # revert patches from upstream that conflict or that we get via other means ApplyOptionalPatch linux-2.6-upstream-reverts.patch -R -ApplyPatch linux-2.6-hotfixes.patch - -# Roland's utrace ptrace replacement. +# utrace ApplyPatch linux-2.6-utrace-revert-make-ptrace-functions-static.patch ApplyPatch linux-2.6-tracehook.patch ApplyPatch linux-2.6-utrace.patch @@ -1231,22 +1178,6 @@ ApplyPatch ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch # Architecture patches # x86(-64) -# Restore reliable stack backtraces, and hopefully -# fix RHBZ #700718 -ApplyPatch x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch - -# -# Intel IOMMU -# -# from 2.6.39.2 -ApplyPatch intel-iommu-flush-unmaps-at-domain_exit.patch -ApplyPatch intel-iommu-only-unlink-device-domains-from-iommu.patch -ApplyPatch intel-iommu-check-for-identity-mapping-candidate-using.patch -ApplyPatch intel-iommu-speed-up-processing-of-the-identity_mapping.patch -ApplyPatch intel-iommu-dont-cache-iova-above-32bit.patch -ApplyPatch intel-iommu-use-coherent-dma-mask-when-requested.patch -ApplyPatch intel-iommu-remove-host-bridge-devices-from-identity.patch -ApplyPatch intel-iommu-add-domain-check-in-domain_remove_one_dev_info.patch # # PowerPC @@ -1289,10 +1220,8 @@ ApplyPatch acpi-ec-add-delay-before-write.patch ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch # Various low-impact patches to aid debugging. -ApplyPatch linux-2.6-debug-sizeof-structs.patch ApplyPatch linux-2.6-debug-taint-vm.patch ApplyPatch linux-2.6-debug-vm-would-have-oomkilled.patch -ApplyPatch linux-2.6-debug-always-inline-kzalloc.patch # # PCI @@ -1302,8 +1231,6 @@ ApplyPatch linux-2.6-defaults-pci_no_msi.patch ApplyPatch linux-2.6-defaults-pci_use_crs.patch # enable ASPM by default on hardware we expect to work ApplyPatch linux-2.6-defaults-aspm.patch -# fixes for ASPM powersave mode -ApplyPatch pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch ApplyPatch pci-enable-aspm-state-clearing-regardless-of-policy.patch # Fix breakage of PCI network adapter names on older Dell systems ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch @@ -1313,14 +1240,10 @@ ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch # # SCSI / block Bits. # -ApplyPatch block-queue-refcount.patch -ApplyPatch block-export-blk_-get-put-_queue.patch -ApplyPatch block-blkdev_get-should-access-bd_disk-only-after.patch # rhbz#577968 ApplyPatch cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch # libata -ApplyPatch ahci-add-another-pci-id-for-marvell.patch # Fix drive detection failure on mvsas (rhbz#705019) ApplyPatch libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch @@ -1336,8 +1259,6 @@ ApplyPatch hda_intel-prealloc-4mb-dmabuffer.patch ApplyPatch linux-2.6-input-kill-stupid-messages.patch ApplyPatch linux-2.6.30-no-pcspkr-modalias.patch ApplyPatch revert-hid-magicmouse-ignore-ivalid-report-id-while-switching.patch -ApplyPatch input-wacom-add-support-for-lenovo-tablet-id-0xe6.patch -ApplyPatch hid-ntrig-deref-unclaimed-input.patch ApplyPatch hid-multitouch-add-support-for-elo-touchsystems.patch # stop floppy.ko from autoloading during udev... @@ -1375,7 +1296,6 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch # DRM core # Nouveau DRM -ApplyPatch drm-ttm-move-notify.patch ApplyOptionalPatch drm-nouveau-fixes.patch ApplyOptionalPatch drm-nouveau-updates.patch @@ -1385,18 +1305,11 @@ ApplyPatch drm-intel-big-hammer.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch drm-intel-edp-fixes.patch -ApplyPatch drm-i915-fix-pipelined-fencing.patch -ApplyPatch drm-intel-eeebox-eb1007-quirk.patch -ApplyPatch drm-intel-restore-mode.patch ApplyPatch drm-i915-snb-irq-stalls-fix.patch ApplyPatch drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch # radeon DRM (add cayman support) ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -R -ApplyPatch drm-radeon-update.patch -ApplyPatch drm-radeon-update2.patch -ApplyPatch drm-radeon-pageflip-oops-fix.patch -ApplyPatch drm-radeon-update3.patch # linux1394 git patches #ApplyPatch linux-2.6-firewire-git-update.patch @@ -1407,7 +1320,6 @@ ApplyPatch linux-2.6-silence-acpi-blacklist.patch # V4L/DVB updates/fixes/experimental drivers # apply if non-empty -ApplyPatch cx88-Fix-HVR4000-IR-keymap.patch -R ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch @@ -1420,11 +1332,6 @@ ApplyPatch add-appleir-usb-driver.patch ApplyPatch neuter_intel_microcode_load.patch -# various fixes for Apple and EFI -ApplyPatch apple_backlight.patch -ApplyPatch efifb_update.patch -ApplyPatch acpi_reboot.patch - # Runtime PM #ApplyPatch linux-2.6-usb-pci-autosuspend.patch ### Broken by implicit notify support & ACPICA rebase @@ -1433,27 +1340,13 @@ ApplyPatch acpi_reboot.patch # rhbz#605888 ApplyPatch dmar-disable-when-ricoh-multifunction.patch -# rhbz#691888 -ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch - ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch -#rhbz 668231 -ApplyPatch linux-2.6-netconsole-deadlock.patch - -# CVE-2011-1581 -ApplyPatch bonding-incorrect-tx-queue-offset.patch - -ApplyPatch scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch - ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch # rhbz#709122 ApplyPatch ath5k-disable-fast-channel-switching-by-default.patch -# rhbz#648732 -ApplyPatch iwlagn-use-cts-to-self-protection-on-5000-adapters-series.patch - # rhbz#589390 ApplyPatch crypto-aesni_intel-merge-with-fpu_ko.patch @@ -2065,6 +1958,9 @@ fi # and build. %changelog +* Wed Jun 29 2011 Dave Jones +- 2.6.39 + * Mon Jun 27 2011 Dave Jones - Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) diff --git a/linux-2.6-acpi-debug-infinite-loop.patch b/linux-2.6-acpi-debug-infinite-loop.patch index 45cb05165..d20025224 100644 --- a/linux-2.6-acpi-debug-infinite-loop.patch +++ b/linux-2.6-acpi-debug-infinite-loop.patch @@ -1,16 +1,3 @@ ---- linux-2.6.34.noarch/drivers/acpi/acpica/dsopcode.c~ 2010-07-01 14:40:44.000000000 -0400 -+++ linux-2.6.34.noarch/drivers/acpi/acpica/dsopcode.c 2010-07-01 14:48:56.000000000 -0400 -@@ -1276,6 +1276,10 @@ acpi_ds_exec_end_control_op(struct acpi_ - * loop does not implement a timeout. - */ - control_state->control.loop_count++; -+ if ((control_state->control.loop_count > 1) && (control_state->control.loop_count % 0xffff == 0)) -+ printk("ACPI: While loop taking a really long time. loop_count=0x%x\n", -+ control_state->control.loop_count); -+ - if (control_state->control.loop_count > - ACPI_MAX_LOOP_ITERATIONS) { - status = AE_AML_INFINITE_LOOP; --- linux-2.6.34.noarch/drivers/acpi/acpica/acconfig.h~ 2010-07-01 14:49:03.000000000 -0400 +++ linux-2.6.34.noarch/drivers/acpi/acpica/acconfig.h 2010-07-01 14:49:17.000000000 -0400 @@ -117,7 +117,7 @@ @@ -22,3 +9,17 @@ /* Maximum sleep allowed via Sleep() operator */ +--- a/drivers/acpi/acpica/dscontrol.c ++++ b/drivers/acpi/acpica/dscontrol.c +@@ -212,6 +212,11 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, + * loop does not implement a timeout. + */ + control_state->control.loop_count++; ++ if ((control_state->control.loop_count > 1) && ++ (control_state->control.loop_count % 0xffff == 0)) ++ printk("ACPI: While loop taking a really long time. loop_count=0x%x\n", ++ control_state->control.loop_count); ++ + if (control_state->control.loop_count > + ACPI_MAX_LOOP_ITERATIONS) { + status = AE_AML_INFINITE_LOOP; diff --git a/linux-2.6-crash-driver.patch b/linux-2.6-crash-driver.patch index 0f11aba0d..512774340 100644 --- a/linux-2.6-crash-driver.patch +++ b/linux-2.6-crash-driver.patch @@ -220,20 +220,18 @@ index 5eb1ba7..3e525d2 100644 /* * Fix up the linear direct mapping of the kernel to avoid cache attribute * conflicts. -diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 3141dd3..153658c 100644 ---- a/drivers/char/Kconfig -+++ b/drivers/char/Kconfig -@@ -471,6 +471,8 @@ config LEGACY_PTYS - security. This option enables these legacy devices; on most - systems, it is safe to say N. +--- linux-2.6.39.noarch/drivers/char/Kconfig~ 2011-06-29 23:41:24.386370545 -0400 ++++ linux-2.6.39.noarch/drivers/char/Kconfig 2011-06-29 23:42:11.984193335 -0400 +@@ -15,6 +15,9 @@ config DEVKMEM + kind of kernel debugging operations. + When in doubt, say "N". +config CRASH -+ tristate "Crash Utility memory driver" - - config LEGACY_PTY_COUNT - int "Maximum number of legacy PTY in use" - ++ tristate "Crash Utility memory driver" ++ + config STALDRV + bool "Stallion multiport serial support" + depends on SERIAL_NONSTANDARD diff --git a/drivers/char/crash.c b/drivers/char/crash.c new file mode 100644 index 0000000..e5437de diff --git a/linux-2.6-debug-always-inline-kzalloc.patch b/linux-2.6-debug-always-inline-kzalloc.patch deleted file mode 100644 index 24f665ca6..000000000 --- a/linux-2.6-debug-always-inline-kzalloc.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 76ec0e2e6d6edf81abc0331d5e7873ef7b2f6019 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Wed, 8 Jul 2009 13:06:01 -0400 -Subject: [PATCH 6/6] fedora: linux-2.6-debug-always-inline-kzalloc.patch - ---- - include/linux/slab.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/include/linux/slab.h b/include/linux/slab.h -index 2da8372..d4ef74f 100644 ---- a/include/linux/slab.h -+++ b/include/linux/slab.h -@@ -310,7 +310,7 @@ static inline void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags) - * @size: how many bytes of memory are required. - * @flags: the type of memory to allocate (see kmalloc). - */ --static inline void *kzalloc(size_t size, gfp_t flags) -+static __always_inline void *kzalloc(size_t size, gfp_t flags) - { - return kmalloc(size, flags | __GFP_ZERO); - } --- -1.6.2.5 - diff --git a/linux-2.6-debug-sizeof-structs.patch b/linux-2.6-debug-sizeof-structs.patch deleted file mode 100644 index e027d98a1..000000000 --- a/linux-2.6-debug-sizeof-structs.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/init/main.c b/init/main.c -index 7449819..98cfaae 100644 ---- a/init/main.c -+++ b/init/main.c -@@ -369,6 +369,11 @@ static void __init setup_nr_cpu_ids(void) - nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1; - } - -+#include <../fs/ext4/ext4.h> -+#include -+#include -+#include -+ - /* Called by boot processor to activate the rest. */ - static void __init smp_init(void) - { -@@ -391,6 +395,16 @@ static void __init smp_init(void) - /* Any cleanup work */ - printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus()); - smp_cpus_done(setup_max_cpus); -+ -+ printk(KERN_DEBUG "sizeof(vma)=%u bytes\n", (unsigned int) sizeof(struct vm_area_struct)); -+ printk(KERN_DEBUG "sizeof(page)=%u bytes\n", (unsigned int) sizeof(struct page)); -+ printk(KERN_DEBUG "sizeof(inode)=%u bytes\n", (unsigned int) sizeof(struct inode)); -+ printk(KERN_DEBUG "sizeof(dentry)=%u bytes\n", (unsigned int) sizeof(struct dentry)); -+ printk(KERN_DEBUG "sizeof(ext3inode)=%u bytes\n", (unsigned int) sizeof(struct ext3_inode_info)); -+ printk(KERN_DEBUG "sizeof(ext4inode)=%u bytes\n", (unsigned int) sizeof(struct ext4_inode_info)); -+ printk(KERN_DEBUG "sizeof(buffer_head)=%u bytes\n", (unsigned int) sizeof(struct buffer_head)); -+ printk(KERN_DEBUG "sizeof(skbuff)=%u bytes\n", (unsigned int) sizeof(struct sk_buff)); -+ printk(KERN_DEBUG "sizeof(task_struct)=%u bytes\n", (unsigned int) sizeof(struct task_struct)); - } - - #endif diff --git a/linux-2.6-hotfixes.patch b/linux-2.6-hotfixes.patch deleted file mode 100644 index 494947322..000000000 --- a/linux-2.6-hotfixes.patch +++ /dev/null @@ -1,15 +0,0 @@ -fixes: -implicit declaration of function kzalloc - ---- linux-2.6.34.noarch/drivers/usb/serial/qcserial.c~ 2010-06-08 15:19:41.000000000 -0400 -+++ linux-2.6.34.noarch/drivers/usb/serial/qcserial.c 2010-06-08 15:19:47.000000000 -0400 -@@ -11,6 +11,7 @@ - * - */ - -+#include - #include - #include - #include - - diff --git a/linux-2.6-i386-nx-emulation.patch b/linux-2.6-i386-nx-emulation.patch index da84cc672..3d2c96874 100644 --- a/linux-2.6-i386-nx-emulation.patch +++ b/linux-2.6-i386-nx-emulation.patch @@ -46,7 +46,7 @@ #endif /* _ASM_X86_DESC_H */ --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h -@@ -7,12 +7,19 @@ +@@ -7,18 +7,25 @@ /* * The x86 doesn't have a mmu context, but * we put the segment information here. @@ -59,10 +59,16 @@ int size; struct mutex lock; void *vdso; + + #ifdef CONFIG_X86_64 + /* True if mm supports a task running in 32 bit compatibility mode. */ + unsigned short ia32_compat; + #endif +#ifdef CONFIG_X86_32 + struct desc_struct user_cs; + unsigned long exec_limit; +#endif + } mm_context_t; #ifdef CONFIG_SMP @@ -132,7 +138,7 @@ .store_gdt = native_store_gdt, --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c -@@ -243,7 +243,10 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, +@@ -243,7 +243,10 @@ int copy_thread(unsigned long clone_flag void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { @@ -141,8 +147,8 @@ set_user_gs(regs, 0); + regs->fs = 0; - set_fs(USER_DS); regs->ds = __USER_DS; + regs->es = __USER_DS; @@ -252,6 +255,11 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) regs->cs = __USER_CS; regs->ip = new_ip; @@ -472,8 +478,8 @@ --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -101,6 +101,9 @@ struct bio_list; - struct fs_struct; struct perf_event_context; + struct blk_plug; +extern int disable_nx; +extern int print_fatal_signals; diff --git a/linux-2.6-netconsole-deadlock.patch b/linux-2.6-netconsole-deadlock.patch deleted file mode 100644 index 677ed760b..000000000 --- a/linux-2.6-netconsole-deadlock.patch +++ /dev/null @@ -1,56 +0,0 @@ -commit 13f172ff26563995049abe73f6eeba828de3c09d -Author: Neil Horman -Date: Fri Apr 22 08:10:59 2011 +0000 - - netconsole: fix deadlock when removing net driver that netconsole is using (v2) - - A deadlock was reported to me recently that occured when netconsole was being - used in a virtual guest. If the virtio_net driver was removed while netconsole - was setup to use an interface that was driven by that driver, the guest - deadlocked. No backtrace was provided because netconsole was the only console - configured, but it became clear pretty quickly what the problem was. In - netconsole_netdev_event, if we get an unregister event, we call - __netpoll_cleanup with the target_list_lock held and irqs disabled. - __netpoll_cleanup can, if pending netpoll packets are waiting call - cancel_delayed_work_sync, which is a sleeping path. the might_sleep call in - that path gets triggered, causing a console warning to be issued. The - netconsole write handler of course tries to take the target_list_lock again, - which we already hold, causing deadlock. - - The fix is pretty striaghtforward. Simply drop the target_list_lock and - re-enable irqs prior to calling __netpoll_cleanup, the re-acquire the lock, and - restart the loop. Confirmed by myself to fix the problem reported. - - Signed-off-by: Neil Horman - CC: "David S. Miller" - Signed-off-by: David S. Miller - -diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c -index dfb67eb..eb41e44 100644 ---- a/drivers/net/netconsole.c -+++ b/drivers/net/netconsole.c -@@ -671,6 +671,7 @@ static int netconsole_netdev_event(struct notifier_block *this, - goto done; - - spin_lock_irqsave(&target_list_lock, flags); -+restart: - list_for_each_entry(nt, &target_list, list) { - netconsole_target_get(nt); - if (nt->np.dev == dev) { -@@ -683,9 +684,16 @@ static int netconsole_netdev_event(struct notifier_block *this, - * rtnl_lock already held - */ - if (nt->np.dev) { -+ spin_unlock_irqrestore( -+ &target_list_lock, -+ flags); - __netpoll_cleanup(&nt->np); -+ spin_lock_irqsave(&target_list_lock, -+ flags); - dev_put(nt->np.dev); - nt->np.dev = NULL; -+ netconsole_target_put(nt); -+ goto restart; - } - /* Fall through */ - case NETDEV_GOING_DOWN: diff --git a/linux-2.6-upstream-reverts.patch b/linux-2.6-upstream-reverts.patch index 157205fb2..e69de29bb 100644 --- a/linux-2.6-upstream-reverts.patch +++ b/linux-2.6-upstream-reverts.patch @@ -1,203 +0,0 @@ -From 97bfd0acd32e9639c9136e03955d574655d5cc2b Mon Sep 17 00:00:00 2001 -From: Dave Airlie -Date: Thu, 19 May 2011 14:14:43 +1000 -Subject: drm/radeon/kms: add wait idle ioctl for eg->cayman - -From: Dave Airlie - -commit 97bfd0acd32e9639c9136e03955d574655d5cc2b upstream. - -None of the latest GPUs had this hooked up, this is necessary for -correct operation in a lot of cases, however we should test this on a few -GPUs in these families as we've had problems in this area before. - -Reviewed-by: Alex Deucher -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/radeon_asic.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/gpu/drm/radeon/radeon_asic.c -+++ b/drivers/gpu/drm/radeon/radeon_asic.c -@@ -782,6 +782,7 @@ static struct radeon_asic evergreen_asic - .hpd_fini = &evergreen_hpd_fini, - .hpd_sense = &evergreen_hpd_sense, - .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, - .gui_idle = &r600_gui_idle, - .pm_misc = &evergreen_pm_misc, - .pm_prepare = &evergreen_pm_prepare, -@@ -828,6 +829,7 @@ static struct radeon_asic sumo_asic = { - .hpd_fini = &evergreen_hpd_fini, - .hpd_sense = &evergreen_hpd_sense, - .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, - .gui_idle = &r600_gui_idle, - .pm_misc = &evergreen_pm_misc, - .pm_prepare = &evergreen_pm_prepare, -@@ -874,6 +876,8 @@ static struct radeon_asic btc_asic = { - .hpd_fini = &evergreen_hpd_fini, - .hpd_sense = &evergreen_hpd_sense, - .hpd_set_polarity = &evergreen_hpd_set_polarity, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, -+ .ioctl_wait_idle = r600_ioctl_wait_idle, - .gui_idle = &r600_gui_idle, - .pm_misc = &evergreen_pm_misc, - .pm_prepare = &evergreen_pm_prepare, -From f25a5c63bfa017498c9adecb24d649ae96ba5c68 Mon Sep 17 00:00:00 2001 -From: Alex Deucher -Date: Thu, 19 May 2011 11:07:57 -0400 -Subject: drm/radeon/evergreen/btc/fusion: setup hdp to invalidate and - flush when asked - -From: Alex Deucher - -commit f25a5c63bfa017498c9adecb24d649ae96ba5c68 upstream. - -This needs to be explicitly set on btc. It's set by default -on evergreen/fusion, so it fine to just unconditionally enable it for -all chips. - -Signed-off-by: Alex Deucher -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman - ---- - drivers/gpu/drm/radeon/evergreen.c | 6 +++++- - drivers/gpu/drm/radeon/evergreend.h | 2 ++ - 2 files changed, 7 insertions(+), 1 deletion(-) - ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -1585,7 +1585,7 @@ static void evergreen_gpu_init(struct ra - u32 sq_stack_resource_mgmt_2; - u32 sq_stack_resource_mgmt_3; - u32 vgt_cache_invalidation; -- u32 hdp_host_path_cntl; -+ u32 hdp_host_path_cntl, tmp; - int i, j, num_shader_engines, ps_thread_count; - - switch (rdev->family) { -@@ -2145,6 +2145,10 @@ static void evergreen_gpu_init(struct ra - for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4) - WREG32(i, 0); - -+ tmp = RREG32(HDP_MISC_CNTL); -+ tmp |= HDP_FLUSH_INVALIDATE_CACHE; -+ WREG32(HDP_MISC_CNTL, tmp); -+ - hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL); - WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl); - ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -64,6 +64,8 @@ - #define GB_BACKEND_MAP 0x98FC - #define DMIF_ADDR_CONFIG 0xBD4 - #define HDP_ADDR_CONFIG 0x2F48 -+#define HDP_MISC_CNTL 0x2F4C -+#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0) - - #define CC_SYS_RB_BACKEND_DISABLE 0x3F88 - #define GC_USER_RB_BACKEND_DISABLE 0x9B7C -From alexdeucher@gmail.com Mon May 9 16:35:34 2011 -From: Alex Deucher -Date: Fri, 6 May 2011 14:29:55 -0400 -Subject: [stable] [PATCH] drm/radeon/kms: fix gart setup on fusion parts (v2) backport -To: stable@kernel.org -Cc: Alex Deucher , airlied@redhat.com, gregkh@suse.de -Message-ID: <1304706595-9781-1-git-send-email-alexdeucher@gmail.com> - -From: Alex Deucher - -Backport of 8aeb96f80232e9a701b5c4715504f4c9173978bd -(drm/radeon/kms: fix gart setup on fusion parts (v2)) -to the stable tree. - -Out of the entire GART/VM subsystem, the hw designers changed -the location of 3 regs. - -v2: airlied: add parameter for userspace to work from. - -Signed-off-by: Alex Deucher -Signed-off-by: Jerome Glisse -Signed-off-by: Dave Airlie -Signed-off-by: Greg Kroah-Hartman ---- - drivers/gpu/drm/radeon/evergreen.c | 17 +++++++++-------- - drivers/gpu/drm/radeon/evergreend.h | 5 +++++ - drivers/gpu/drm/radeon/radeon_kms.c | 3 +++ - include/drm/radeon_drm.h | 1 + - 4 files changed, 18 insertions(+), 8 deletions(-) - ---- a/drivers/gpu/drm/radeon/evergreen.c -+++ b/drivers/gpu/drm/radeon/evergreen.c -@@ -869,9 +869,15 @@ int evergreen_pcie_gart_enable(struct ra - SYSTEM_ACCESS_MODE_NOT_IN_SYS | - SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | - EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5); -- WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); -- WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); -- WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); -+ if (rdev->flags & RADEON_IS_IGP) { -+ WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp); -+ WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp); -+ WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp); -+ } else { -+ WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); -+ WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); -+ WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); -+ } - WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); - WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); - WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); -@@ -2930,11 +2936,6 @@ static int evergreen_startup(struct rade - rdev->asic->copy = NULL; - dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); - } -- /* XXX: ontario has problems blitting to gart at the moment */ -- if (rdev->family == CHIP_PALM) { -- rdev->asic->copy = NULL; -- radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); -- } - - /* allocate wb buffer */ - r = radeon_wb_init(rdev); ---- a/drivers/gpu/drm/radeon/evergreend.h -+++ b/drivers/gpu/drm/radeon/evergreend.h -@@ -221,6 +221,11 @@ - #define MC_VM_MD_L1_TLB0_CNTL 0x2654 - #define MC_VM_MD_L1_TLB1_CNTL 0x2658 - #define MC_VM_MD_L1_TLB2_CNTL 0x265C -+ -+#define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C -+#define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 -+#define FUS_MC_VM_MD_L1_TLB2_CNTL 0x2664 -+ - #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C - #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 - #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 ---- a/drivers/gpu/drm/radeon/radeon_kms.c -+++ b/drivers/gpu/drm/radeon/radeon_kms.c -@@ -205,6 +205,9 @@ int radeon_info_ioctl(struct drm_device - /* return clock value in KHz */ - value = rdev->clock.spll.reference_freq * 10; - break; -+ case RADEON_INFO_FUSION_GART_WORKING: -+ value = 1; -+ break; - default: - DRM_DEBUG_KMS("Invalid request %d\n", info->request); - return -EINVAL; ---- a/include/drm/radeon_drm.h -+++ b/include/drm/radeon_drm.h -@@ -908,6 +908,7 @@ struct drm_radeon_cs { - #define RADEON_INFO_WANT_HYPERZ 0x07 - #define RADEON_INFO_WANT_CMASK 0x08 /* get access to CMASK on r300 */ - #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */ -+#define RADEON_INFO_FUSION_GART_WORKING 0x0c /* fusion writes to GTT were broken before this */ - - struct drm_radeon_info { - uint32_t request; diff --git a/linux-2.6-utrace-ptrace.patch b/linux-2.6-utrace-ptrace.patch index 367deb966..55c6f617c 100644 --- a/linux-2.6-utrace-ptrace.patch +++ b/linux-2.6-utrace-ptrace.patch @@ -48,7 +48,7 @@ new file mode 100644 index ...a5bcb9e 100644 --- /dev/null +++ b/kernel/ptrace-utrace.c -@@ -0,0 +1,1187 @@ +@@ -0,0 +1,1186 @@ +/* + * linux/kernel/ptrace.c + * @@ -65,7 +65,6 @@ index ...a5bcb9e 100644 +#include +#include +#include -+#include +#include +#include +#include @@ -1248,389 +1247,6 @@ index e275608..72ea65c 100644 #include #include #include -@@ -24,7 +23,320 @@ - #include - #include - -+int __ptrace_may_access(struct task_struct *task, unsigned int mode) -+{ -+ const struct cred *cred = current_cred(), *tcred; -+ -+ /* May we inspect the given task? -+ * This check is used both for attaching with ptrace -+ * and for allowing access to sensitive information in /proc. -+ * -+ * ptrace_attach denies several cases that /proc allows -+ * because setting up the necessary parent/child relationship -+ * or halting the specified task is impossible. -+ */ -+ int dumpable = 0; -+ /* Don't let security modules deny introspection */ -+ if (task == current) -+ return 0; -+ rcu_read_lock(); -+ tcred = __task_cred(task); -+ if ((cred->uid != tcred->euid || -+ cred->uid != tcred->suid || -+ cred->uid != tcred->uid || -+ cred->gid != tcred->egid || -+ cred->gid != tcred->sgid || -+ cred->gid != tcred->gid) && -+ !capable(CAP_SYS_PTRACE)) { -+ rcu_read_unlock(); -+ return -EPERM; -+ } -+ rcu_read_unlock(); -+ smp_rmb(); -+ if (task->mm) -+ dumpable = get_dumpable(task->mm); -+ if (!dumpable && !capable(CAP_SYS_PTRACE)) -+ return -EPERM; -+ -+ return security_ptrace_access_check(task, mode); -+} -+ -+bool ptrace_may_access(struct task_struct *task, unsigned int mode) -+{ -+ int err; -+ task_lock(task); -+ err = __ptrace_may_access(task, mode); -+ task_unlock(task); -+ return !err; -+} -+ -+/* -+ * Called with irqs disabled, returns true if childs should reap themselves. -+ */ -+static int ignoring_children(struct sighand_struct *sigh) -+{ -+ int ret; -+ spin_lock(&sigh->siglock); -+ ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || -+ (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); -+ spin_unlock(&sigh->siglock); -+ return ret; -+} -+ -+/* -+ * Called with tasklist_lock held for writing. -+ * Unlink a traced task, and clean it up if it was a traced zombie. -+ * Return true if it needs to be reaped with release_task(). -+ * (We can't call release_task() here because we already hold tasklist_lock.) -+ * -+ * If it's a zombie, our attachedness prevented normal parent notification -+ * or self-reaping. Do notification now if it would have happened earlier. -+ * If it should reap itself, return true. -+ * -+ * If it's our own child, there is no notification to do. But if our normal -+ * children self-reap, then this child was prevented by ptrace and we must -+ * reap it now, in that case we must also wake up sub-threads sleeping in -+ * do_wait(). -+ */ -+bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -+{ -+ __ptrace_unlink(p); -+ -+ if (p->exit_state == EXIT_ZOMBIE) { -+ if (!task_detached(p) && thread_group_empty(p)) { -+ if (!same_thread_group(p->real_parent, tracer)) -+ do_notify_parent(p, p->exit_signal); -+ else if (ignoring_children(tracer->sighand)) { -+ __wake_up_parent(p, tracer); -+ p->exit_signal = -1; -+ } -+ } -+ if (task_detached(p)) { -+ /* Mark it as in the process of being reaped. */ -+ p->exit_state = EXIT_DEAD; -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -+{ -+ int copied = 0; -+ -+ while (len > 0) { -+ char buf[128]; -+ int this_len, retval; -+ -+ this_len = (len > sizeof(buf)) ? sizeof(buf) : len; -+ retval = access_process_vm(tsk, src, buf, this_len, 0); -+ if (!retval) { -+ if (copied) -+ break; -+ return -EIO; -+ } -+ if (copy_to_user(dst, buf, retval)) -+ return -EFAULT; -+ copied += retval; -+ src += retval; -+ dst += retval; -+ len -= retval; -+ } -+ return copied; -+} -+ -+int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -+{ -+ int copied = 0; -+ -+ while (len > 0) { -+ char buf[128]; -+ int this_len, retval; -+ -+ this_len = (len > sizeof(buf)) ? sizeof(buf) : len; -+ if (copy_from_user(buf, src, this_len)) -+ return -EFAULT; -+ retval = access_process_vm(tsk, dst, buf, this_len, 1); -+ if (!retval) { -+ if (copied) -+ break; -+ return -EIO; -+ } -+ copied += retval; -+ src += retval; -+ dst += retval; -+ len -= retval; -+ } -+ return copied; -+} -+ -+#ifdef CONFIG_HAVE_ARCH_TRACEHOOK -+ -+static const struct user_regset * -+find_regset(const struct user_regset_view *view, unsigned int type) -+{ -+ const struct user_regset *regset; -+ int n; -+ -+ for (n = 0; n < view->n; ++n) { -+ regset = view->regsets + n; -+ if (regset->core_note_type == type) -+ return regset; -+ } -+ -+ return NULL; -+} -+ -+int ptrace_regset(struct task_struct *task, int req, unsigned int type, -+ struct iovec *kiov) -+{ -+ const struct user_regset_view *view = task_user_regset_view(task); -+ const struct user_regset *regset = find_regset(view, type); -+ int regset_no; -+ -+ if (!regset || (kiov->iov_len % regset->size) != 0) -+ return -EINVAL; -+ -+ regset_no = regset - view->regsets; -+ kiov->iov_len = min(kiov->iov_len, -+ (__kernel_size_t) (regset->n * regset->size)); -+ -+ if (req == PTRACE_GETREGSET) -+ return copy_regset_to_user(task, view, regset_no, 0, -+ kiov->iov_len, kiov->iov_base); -+ else -+ return copy_regset_from_user(task, view, regset_no, 0, -+ kiov->iov_len, kiov->iov_base); -+} -+ -+#endif -+ -+static struct task_struct *ptrace_get_task_struct(pid_t pid) -+{ -+ struct task_struct *child; -+ -+ rcu_read_lock(); -+ child = find_task_by_vpid(pid); -+ if (child) -+ get_task_struct(child); -+ rcu_read_unlock(); -+ -+ if (!child) -+ return ERR_PTR(-ESRCH); -+ return child; -+} -+ -+#ifndef arch_ptrace_attach -+#define arch_ptrace_attach(child) do { } while (0) -+#endif -+ -+SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr, -+ unsigned long, data) -+{ -+ struct task_struct *child; -+ long ret; -+ -+ if (request == PTRACE_TRACEME) { -+ ret = ptrace_traceme(); -+ if (!ret) -+ arch_ptrace_attach(current); -+ goto out; -+ } - -+ child = ptrace_get_task_struct(pid); -+ if (IS_ERR(child)) { -+ ret = PTR_ERR(child); -+ goto out; -+ } -+ -+ if (request == PTRACE_ATTACH) { -+ ret = ptrace_attach(child); -+ /* -+ * Some architectures need to do book-keeping after -+ * a ptrace attach. -+ */ -+ if (!ret) -+ arch_ptrace_attach(child); -+ goto out_put_task_struct; -+ } -+ -+ ret = ptrace_check_attach(child, request == PTRACE_KILL); -+ if (ret < 0) -+ goto out_put_task_struct; -+ -+ ret = arch_ptrace(child, request, addr, data); -+ -+ out_put_task_struct: -+ put_task_struct(child); -+ out: -+ return ret; -+} -+ -+int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr, -+ unsigned long data) -+{ -+ unsigned long tmp; -+ int copied; -+ -+ copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); -+ if (copied != sizeof(tmp)) -+ return -EIO; -+ return put_user(tmp, (unsigned long __user *)data); -+} -+ -+int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr, -+ unsigned long data) -+{ -+ int copied; -+ -+ copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); -+ return (copied == sizeof(data)) ? 0 : -EIO; -+} -+ -+#if defined CONFIG_COMPAT -+#include -+ -+asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, -+ compat_long_t addr, compat_long_t data) -+{ -+ struct task_struct *child; -+ long ret; -+ -+ if (request == PTRACE_TRACEME) { -+ ret = ptrace_traceme(); -+ goto out; -+ } -+ -+ child = ptrace_get_task_struct(pid); -+ if (IS_ERR(child)) { -+ ret = PTR_ERR(child); -+ goto out; -+ } -+ -+ if (request == PTRACE_ATTACH) { -+ ret = ptrace_attach(child); -+ /* -+ * Some architectures need to do book-keeping after -+ * a ptrace attach. -+ */ -+ if (!ret) -+ arch_ptrace_attach(child); -+ goto out_put_task_struct; -+ } -+ -+ ret = ptrace_check_attach(child, request == PTRACE_KILL); -+ if (!ret) -+ ret = compat_arch_ptrace(child, request, addr, data); -+ -+ out_put_task_struct: -+ put_task_struct(child); -+ out: -+ return ret; -+} -+#endif /* CONFIG_COMPAT */ -+ -+#ifndef CONFIG_UTRACE - /* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. -@@ -117,61 +429,6 @@ int ptrace_check_attach(struct task_stru - return ret; - } - --int __ptrace_may_access(struct task_struct *task, unsigned int mode) --{ -- const struct cred *cred = current_cred(), *tcred; -- -- /* May we inspect the given task? -- * This check is used both for attaching with ptrace -- * and for allowing access to sensitive information in /proc. -- * -- * ptrace_attach denies several cases that /proc allows -- * because setting up the necessary parent/child relationship -- * or halting the specified task is impossible. -- */ -- int dumpable = 0; -- /* Don't let security modules deny introspection */ -- if (task == current) -- return 0; -- rcu_read_lock(); -- tcred = __task_cred(task); -- if ((cred->uid != tcred->euid || -- cred->uid != tcred->suid || -- cred->uid != tcred->uid || -- cred->gid != tcred->egid || -- cred->gid != tcred->sgid || -- cred->gid != tcred->gid) && -- !capable(CAP_SYS_PTRACE)) { -- rcu_read_unlock(); -- return -EPERM; -- } -- rcu_read_unlock(); -- smp_rmb(); -- if (task->mm) -- dumpable = get_dumpable(task->mm); -- if (!dumpable && !capable(CAP_SYS_PTRACE)) -- return -EPERM; -- -- return security_ptrace_access_check(task, mode); --} -- --bool ptrace_may_access(struct task_struct *task, unsigned int mode) --{ -- int err; -- task_lock(task); -- err = __ptrace_may_access(task, mode); -- task_unlock(task); -- return !err; --} -- --/* -- * For experimental use of utrace, exclude ptrace on the same task. -- */ --static inline bool exclude_ptrace(struct task_struct *task) --{ -- return unlikely(!!task_utrace_flags(task)); --} -- - int ptrace_attach(struct task_struct *task) - { - int retval; @@ -195,8 +452,6 @@ int ptrace_attach(struct task_struct *ta task_lock(task); @@ -1955,11 +1571,399 @@ index e275608..72ea65c 100644 int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { -@@ -851,45 +876,8 @@ int compat_ptrace_request(struct task_st +--- linux-2.6.39.noarch/kernel/ptrace.c~ 2011-06-30 01:26:39.872164118 -0400 ++++ linux-2.6.39.noarch/kernel/ptrace.c 2011-06-30 01:30:09.682400285 -0400 +@@ -24,8 +24,321 @@ + #include + #include ++int __ptrace_may_access(struct task_struct *task, unsigned int mode) ++{ ++ const struct cred *cred = current_cred(), *tcred; ++ ++ /* May we inspect the given task? ++ * This check is used both for attaching with ptrace ++ * and for allowing access to sensitive information in /proc. ++ * ++ * ptrace_attach denies several cases that /proc allows ++ * because setting up the necessary parent/child relationship ++ * or halting the specified task is impossible. ++ */ ++ int dumpable = 0; ++ /* Don't let security modules deny introspection */ ++ if (task == current) ++ return 0; ++ rcu_read_lock(); ++ tcred = __task_cred(task); ++ if ((cred->uid != tcred->euid || ++ cred->uid != tcred->suid || ++ cred->uid != tcred->uid || ++ cred->gid != tcred->egid || ++ cred->gid != tcred->sgid || ++ cred->gid != tcred->gid) && ++ !capable(CAP_SYS_PTRACE)) { ++ rcu_read_unlock(); ++ return -EPERM; ++ } ++ rcu_read_unlock(); ++ smp_rmb(); ++ if (task->mm) ++ dumpable = get_dumpable(task->mm); ++ if (!dumpable && !capable(CAP_SYS_PTRACE)) ++ return -EPERM; ++ ++ return security_ptrace_access_check(task, mode); ++} ++ ++bool ptrace_may_access(struct task_struct *task, unsigned int mode) ++{ ++ int err; ++ task_lock(task); ++ err = __ptrace_may_access(task, mode); ++ task_unlock(task); ++ return !err; ++} + + /* ++ * Called with irqs disabled, returns true if childs should reap themselves. ++ */ ++static int ignoring_children(struct sighand_struct *sigh) ++{ ++ int ret; ++ spin_lock(&sigh->siglock); ++ ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || ++ (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); ++ spin_unlock(&sigh->siglock); ++ return ret; ++} ++ ++/* ++ * Called with tasklist_lock held for writing. ++ * Unlink a traced task, and clean it up if it was a traced zombie. ++ * Return true if it needs to be reaped with release_task(). ++ * (We can't call release_task() here because we already hold tasklist_lock.) ++ * ++ * If it's a zombie, our attachedness prevented normal parent notification ++ * or self-reaping. Do notification now if it would have happened earlier. ++ * If it should reap itself, return true. ++ * ++ * If it's our own child, there is no notification to do. But if our normal ++ * children self-reap, then this child was prevented by ptrace and we must ++ * reap it now, in that case we must also wake up sub-threads sleeping in ++ * do_wait(). ++ */ ++bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) ++{ ++ __ptrace_unlink(p); ++ ++ if (p->exit_state == EXIT_ZOMBIE) { ++ if (!task_detached(p) && thread_group_empty(p)) { ++ if (!same_thread_group(p->real_parent, tracer)) ++ do_notify_parent(p, p->exit_signal); ++ else if (ignoring_children(tracer->sighand)) { ++ __wake_up_parent(p, tracer); ++ p->exit_signal = -1; ++ } ++ } ++ if (task_detached(p)) { ++ /* Mark it as in the process of being reaped. */ ++ p->exit_state = EXIT_DEAD; ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) ++{ ++ int copied = 0; ++ ++ while (len > 0) { ++ char buf[128]; ++ int this_len, retval; ++ ++ this_len = (len > sizeof(buf)) ? sizeof(buf) : len; ++ retval = access_process_vm(tsk, src, buf, this_len, 0); ++ if (!retval) { ++ if (copied) ++ break; ++ return -EIO; ++ } ++ if (copy_to_user(dst, buf, retval)) ++ return -EFAULT; ++ copied += retval; ++ src += retval; ++ dst += retval; ++ len -= retval; ++ } ++ return copied; ++} ++ ++int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) ++{ ++ int copied = 0; ++ ++ while (len > 0) { ++ char buf[128]; ++ int this_len, retval; ++ ++ this_len = (len > sizeof(buf)) ? sizeof(buf) : len; ++ if (copy_from_user(buf, src, this_len)) ++ return -EFAULT; ++ retval = access_process_vm(tsk, dst, buf, this_len, 1); ++ if (!retval) { ++ if (copied) ++ break; ++ return -EIO; ++ } ++ copied += retval; ++ src += retval; ++ dst += retval; ++ len -= retval; ++ } ++ return copied; ++} ++ ++#ifdef CONFIG_HAVE_ARCH_TRACEHOOK ++ ++static const struct user_regset * ++find_regset(const struct user_regset_view *view, unsigned int type) ++{ ++ const struct user_regset *regset; ++ int n; ++ ++ for (n = 0; n < view->n; ++n) { ++ regset = view->regsets + n; ++ if (regset->core_note_type == type) ++ return regset; ++ } ++ ++ return NULL; ++} ++ ++int ptrace_regset(struct task_struct *task, int req, unsigned int type, ++ struct iovec *kiov) ++{ ++ const struct user_regset_view *view = task_user_regset_view(task); ++ const struct user_regset *regset = find_regset(view, type); ++ int regset_no; ++ ++ if (!regset || (kiov->iov_len % regset->size) != 0) ++ return -EINVAL; ++ ++ regset_no = regset - view->regsets; ++ kiov->iov_len = min(kiov->iov_len, ++ (__kernel_size_t) (regset->n * regset->size)); ++ ++ if (req == PTRACE_GETREGSET) ++ return copy_regset_to_user(task, view, regset_no, 0, ++ kiov->iov_len, kiov->iov_base); ++ else ++ return copy_regset_from_user(task, view, regset_no, 0, ++ kiov->iov_len, kiov->iov_base); ++} ++ ++#endif ++ ++static struct task_struct *ptrace_get_task_struct(pid_t pid) ++{ ++ struct task_struct *child; ++ ++ rcu_read_lock(); ++ child = find_task_by_vpid(pid); ++ if (child) ++ get_task_struct(child); ++ rcu_read_unlock(); ++ ++ if (!child) ++ return ERR_PTR(-ESRCH); ++ return child; ++} ++ ++#ifndef arch_ptrace_attach ++#define arch_ptrace_attach(child) do { } while (0) ++#endif ++ ++SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr, ++ unsigned long, data) ++{ ++ struct task_struct *child; ++ long ret; ++ ++ if (request == PTRACE_TRACEME) { ++ ret = ptrace_traceme(); ++ if (!ret) ++ arch_ptrace_attach(current); ++ goto out; ++ } ++ ++ child = ptrace_get_task_struct(pid); ++ if (IS_ERR(child)) { ++ ret = PTR_ERR(child); ++ goto out; ++ } ++ ++ if (request == PTRACE_ATTACH) { ++ ret = ptrace_attach(child); ++ /* ++ * Some architectures need to do book-keeping after ++ * a ptrace attach. ++ */ ++ if (!ret) ++ arch_ptrace_attach(child); ++ goto out_put_task_struct; ++ } ++ ++ ret = ptrace_check_attach(child, request == PTRACE_KILL); ++ if (ret < 0) ++ goto out_put_task_struct; ++ ++ ret = arch_ptrace(child, request, addr, data); ++ ++ out_put_task_struct: ++ put_task_struct(child); ++ out: ++ return ret; ++} ++ ++int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr, ++ unsigned long data) ++{ ++ unsigned long tmp; ++ int copied; ++ ++ copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); ++ if (copied != sizeof(tmp)) ++ return -EIO; ++ return put_user(tmp, (unsigned long __user *)data); ++} ++ ++int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr, ++ unsigned long data) ++{ ++ int copied; ++ ++ copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); ++ return (copied == sizeof(data)) ? 0 : -EIO; ++} ++ ++#if defined CONFIG_COMPAT ++#include ++ ++asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, ++ compat_long_t addr, compat_long_t data) ++{ ++ struct task_struct *child; ++ long ret; ++ ++ if (request == PTRACE_TRACEME) { ++ ret = ptrace_traceme(); ++ goto out; ++ } ++ ++ child = ptrace_get_task_struct(pid); ++ if (IS_ERR(child)) { ++ ret = PTR_ERR(child); ++ goto out; ++ } ++ ++ if (request == PTRACE_ATTACH) { ++ ret = ptrace_attach(child); ++ /* ++ * Some architectures need to do book-keeping after ++ * a ptrace attach. ++ */ ++ if (!ret) ++ arch_ptrace_attach(child); ++ goto out_put_task_struct; ++ } ++ ++ ret = ptrace_check_attach(child, request == PTRACE_KILL); ++ if (!ret) ++ ret = compat_arch_ptrace(child, request, addr, data); ++ ++ out_put_task_struct: ++ put_task_struct(child); ++ out: ++ return ret; ++} ++#endif /* CONFIG_COMPAT */ ++ ++#ifndef CONFIG_UTRACE ++/* + * ptrace a task: make the debugger its new parent and + * move it to the ptrace list. + * +@@ -117,64 +430,6 @@ int ptrace_check_attach(struct task_stru return ret; } + +-int __ptrace_may_access(struct task_struct *task, unsigned int mode) +-{ +- const struct cred *cred = current_cred(), *tcred; - +- /* May we inspect the given task? +- * This check is used both for attaching with ptrace +- * and for allowing access to sensitive information in /proc. +- * +- * ptrace_attach denies several cases that /proc allows +- * because setting up the necessary parent/child relationship +- * or halting the specified task is impossible. +- */ +- int dumpable = 0; +- /* Don't let security modules deny introspection */ +- if (task == current) +- return 0; +- rcu_read_lock(); +- tcred = __task_cred(task); +- if (cred->user->user_ns == tcred->user->user_ns && +- (cred->uid == tcred->euid && +- cred->uid == tcred->suid && +- cred->uid == tcred->uid && +- cred->gid == tcred->egid && +- cred->gid == tcred->sgid && +- cred->gid == tcred->gid)) +- goto ok; +- if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE)) +- goto ok; +- rcu_read_unlock(); +- return -EPERM; +-ok: +- rcu_read_unlock(); +- smp_rmb(); +- if (task->mm) +- dumpable = get_dumpable(task->mm); +- if (!dumpable && !task_ns_capable(task, CAP_SYS_PTRACE)) +- return -EPERM; +- +- return security_ptrace_access_check(task, mode); +-} +- +-bool ptrace_may_access(struct task_struct *task, unsigned int mode) +-{ +- int err; +- task_lock(task); +- err = __ptrace_may_access(task, mode); +- task_unlock(task); +- return !err; +-} +- +-/* +- * For experimental use of utrace, exclude ptrace on the same task. +- */ +-static inline bool exclude_ptrace(struct task_struct *task) +-{ +- return unlikely(!!task_utrace_flags(task)); +-} +- + int ptrace_attach(struct task_struct *task) + { + int retval; +@@ -624,44 +879,8 @@ int compat_ptrace_request(struct task_st + return ret; + } + -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ @@ -1998,7 +2002,7 @@ index e275608..72ea65c 100644 - return ret; -} #endif /* CONFIG_COMPAT */ -+#endif /* CONFIG_UTRACE */ ++#endif /* CONFIG_UTRACE */ #ifdef CONFIG_HAVE_HW_BREAKPOINT int ptrace_get_breakpoints(struct task_struct *tsk) diff --git a/linux-2.6-v4l-dvb-experimental.patch b/linux-2.6-v4l-dvb-experimental.patch index 308ca6351..e69de29bb 100644 --- a/linux-2.6-v4l-dvb-experimental.patch +++ b/linux-2.6-v4l-dvb-experimental.patch @@ -1,1326 +0,0 @@ -commit 9069f7f1ce7309cba021ac9c3527526d8524bd04 -Author: Jarod Wilson -Date: Mon Apr 25 13:50:50 2011 -0400 - - [media] ite-cir: modular build on ppc requires delay.h include - - Signed-off-by: Jarod Wilson - -commit 50f19c24801caaa6d846c62cef93ee54f6e6914f -Author: Jarod Wilson -Date: Mon Apr 25 13:48:18 2011 -0400 - - [media] mceusb: add Dell transceiver ID - - Add device ID for a Dell-branded, Philips device ID transceiver reported - by an OpenELEC user on their forums. - - http://openelec.tv/forum/27-hardware-support/5622-adding-support-for-an-ir-receiver--dell-branded--#5622 - - Signed-off-by: Jarod Wilson - -commit d9193f3784352638b355c9a24c16f1a2e14b0548 -Author: Jarod Wilson -Date: Thu Apr 21 14:21:47 2011 -0400 - - [media] nuvoton-cir: minor tweaks to rc dev init - - - Set a default timeout (matching mceusb.c) and use - ir_raw_event_store_with_filter, which leads to better behavior when - using lirc userspace decoding with this hardware - - Fill in rx_resolution with the value we're using here (50us) - - Signed-off-by: Jarod Wilson - -commit 02210203eb4df7fdf1156b24fcf2b7e2a20bf29c -Author: Jarod Wilson -Date: Tue Apr 19 15:47:34 2011 -0400 - - [media] mceusb: Formosa e017 device has no tx - - Per hardware provided to me, the Formosa Industrial Computing eHome - Infrared Receiver, 0x147a:0xe017, has no tx capability, it is rx only. - - Thanks go to Paul Rae for the hardware. - - Signed-off-by: Jarod Wilson - -commit 5919687ea8e0d3ee093b6edc4e24e30c1a8a60dc -Author: Jarod Wilson -Date: Tue Apr 19 14:31:40 2011 -0400 - - hid: flesh out support for tivo slide remote - - This patch finishes off adding full support for the TiVo Slide remote, - which is a mostly pure HID device from the perspective of the kernel. - There are a few mappings that use a vendor-specific usage page, and a - few keys in the consumer usage page that I think make sense to remap - slightly, to better fit their key labels' intended use. Doing this in a - stand-alone hid-tivo.c makes the modifications only matter for this - specific device. - - What's actually connected to the computer is a Broadcom-made usb dongle, - which has an embedded hub, bluetooth adapter, mouse and keyboard - devices. You pair with the dongle, then the remote sends data that its - converted into HID on the keyboard interface (the mouse interface - doesn't do anything interesting, so far as I can tell). - - lsusb for this device: - Bus 004 Device 005: ID 0a5c:2190 Broadcom Corp. - Bus 004 Device 004: ID 0a5c:4503 Broadcom Corp. - Bus 004 Device 003: ID 150a:1201 - Bus 004 Device 002: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth) - - Speaking of the keyboard interface, the remote actually does contain a - keyboard as well. The top slides away, revealing a reasonably functional - qwerty keyboard (not unlike many slide cell phones), thus the product - name. - - Applies cleanly to hid master, tested w/a 2.6.38.3-based Fedora kernel - and a 2.6.32-based Red Hat Enterprise Linux 6 kernel. - - CC: Jiri Kosina - Signed-off-by: Jarod Wilson - -commit f5d27c83d8b1d1db7d727d4d33ae3df1357c0f03 -Author: Jarod Wilson -Date: Thu Mar 24 17:08:00 2011 -0400 - - rc: add an Apple remote keymap - - Signed-off-by: Jarod Wilson - -commit 9942d577525ebac939c155aaeb18e97e1282c923 -Author: Jarod Wilson -Date: Tue Apr 12 12:38:27 2011 -0400 - - [media] rc/nuvoton-cir: enable CIR on w83667hg chip variant - - Thanks to some excellent investigative work by Douglas Clowes, it was - uncovered that the older w83667hg Nuvoton chip functions with this - driver after actually enabling the CIR function via its multi-function - chip config register. The CIR and CIR wide-band sensor enable bits are - just in a different place on this hardware, so we only poke register - 0x27 on 677 hardware now, and we poke register 0x2c on the 667 now. - - Reported-by: Douglas Clowes - Signed-off-by: Jarod Wilson - -commit 92e839f5added53445aa2c447d69ea1c399e3113 -Author: Jarod Wilson -Date: Tue Apr 12 13:00:07 2011 -0400 - - [media] rc/nuvoton-cir: only warn about unknown chips - - There are additional chip IDs that report a PNP ID of NTN0530, which we - were refusing to load on. Instead, lets just warn if we encounter an - unknown chip, as there's a chance it will work just fine. - - Also, expand the list of known hardware to include both an earlier and a - later generation chip that this driver should function with. Douglas has - an older w83667hg variant, that with a touch more work, will be - supported by this driver, and Lutz has a newer w83677hg variant that - works without any further modifications to the driver. - - Reported-by: Douglas Clowes - Reported-by: Lutz Sammer - Signed-off-by: Jarod Wilson - -commit 8cc98ca72fe0a5c0a5299057edf24690c6940098 -Author: Jarod Wilson -Date: Tue Apr 5 17:42:30 2011 -0400 - - [media] rc: further key name standardization - - Use the newly introduced KEY_IMAGES where appropriate, and standardize - on KEY_MEDIA for media center/application launcher button (such as the - Windows logo key on the Windows Media Center Ed. remotes). - - Signed-off-by: Jarod Wilson - -commit 29d1ac85998862cc4cb7629461358e932363c358 -Author: Jarod Wilson -Date: Thu Mar 24 15:43:45 2011 -0400 - - lirc_sasem: key debug spew off debug modparam - - Signed-off-by: Jarod Wilson - -commit 9965e8d8e0035e56e11e1ad6c359877e51749b34 -Author: Jarod Wilson -Date: Thu Mar 24 11:56:16 2011 -0400 - - ttusb-budget: driver has a debug param, use it - - Remove DEBUG define, key debug spew off of the module's debug param that - already exists. - - Signed-off-by: Jarod Wilson - -commit 10fabf1f9cf8c1d1b579ab549bf4429ad13e0219 -Author: Jarod Wilson -Date: Thu Mar 24 11:54:41 2011 -0400 - - drx397xD: remove unused DEBUG define - - Signed-off-by: Jarod Wilson - -commit aa17ba00097df21cd0392e8aea41e93460e25007 -Author: Jarod Wilson -Date: Thu Mar 24 11:59:10 2011 -0400 - - mceusb: tivo transceiver should default to tivo keymap - - Signed-off-by: Jarod Wilson - -commit 02a5f7ed83b1da82f78b759a293cd15170afe611 -Author: Jarod Wilson -Date: Thu Mar 24 11:58:48 2011 -0400 - - rc: add tivo/nero liquidtv keymap - - Signed-off-by: Jarod Wilson - -commit db27bf543d740530ca0c1ab9fa7f3386f998e87c -Author: Jarod Wilson -Date: Mon Apr 11 17:33:28 2011 -0400 - - hid: assorted usage updates from hut 1.12 - - I've got a Tivo Slide bluetooth remote/dongle, which uses a fair number - of hid usages that aren't currently mapped in hid-input.c. I'd initially - written additions to hid-input.c with just this device in mind, - including some bits that were specific to the device. This go around, - I'm looking at adding/correcting as many generic HID usages from the HID - Usage Tables, version 1.12, as I can -- which also serves to enable all - but four of the buttons on the Tivo Slide remote[*]. - - Outside of fixing the obviously incorrect mapping of 0xc 0x45 from - KEY_RADIO to KEY_RIGHT, and making use of the new KEY_IMAGES (just added - in 2.6.39-rc4) for AL Image Browser instead of KEY_MEDIA, these are - purely additions, and thus should have no negative impact on any already - functional HID devices. Most of the added mappings seemed to be - perfectly logical to me, but there were a few that were mapped on more - of an "I think this makes the most sense" basis. - - [*] I'll handle the last four tivo buttons via an hid-tivo.c follow-up. - - CC: Dmitry Torokhov - CC: Jiri Kosina - Signed-off-by: Jarod Wilson - -commit 967bc222e57b94cf12cb4ad55383dec885f1755c -Author: Jarod Wilson -Date: Wed Apr 6 09:54:01 2011 -0400 - - input: add KEY_IMAGES specifically for AL Image Browser - - Many media center remotes have buttons intended for jumping straight to - one type of media browser or another -- commonly, images/photos/pictures, - audio/music, television, and movies. At present, remotes with an images - or photos or pictures button use any number of different keycodes which - sort of maybe fit. I've seen at least KEY_MEDIA, KEY_CAMERA, - KEY_GRAPHICSEDITOR and KEY_PRESENTATION. None of those seem quite right. - In my mind, KEY_MEDIA should be something more like a media center - application launcher (and I'd like to standardize on that for things - like the windows media center button on the mce remotes). KEY_CAMERA is - used in a lot of webcams, and typically means "take a picture now". - KEY_GRAPHICSEDITOR implies an editor, not a browser. KEY_PRESENTATION - might be the closest fit here, if you think "photo slide show", but it - may well be more intended for "run application in full-screen - presentation mode" or to launch something like magicpoint, I dunno. - And thus, I'd like to have a KEY_IMAGES, which matches the HID Usage AL - Image Browser, the meaning of which I think is crystal-clear. I believe - AL Audio Browser is already covered by KEY_AUDIO, and AL Movie Browser - by KEY_VIDEO, so I'm also adding appropriate comments next to those - keys. - - Signed-off-by: Jarod Wilson - ---- - drivers/hid/Kconfig | 6 + - drivers/hid/Makefile | 1 + - drivers/hid/hid-ids.h | 3 + - drivers/hid/hid-input.c | 60 ++++++++++-- - drivers/hid/hid-tivo.c | 89 ++++++++++++++++++ - drivers/media/dvb/dvb-usb/dibusb-common.c | 2 +- - drivers/media/dvb/dvb-usb/m920x.c | 16 ++-- - drivers/media/dvb/dvb-usb/nova-t-usb2.c | 2 +- - drivers/media/dvb/frontends/drx397xD.c | 1 - - drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 60 ++++++------- - drivers/media/rc/keymaps/Makefile | 2 + - drivers/media/rc/keymaps/rc-apple.c | 55 +++++++++++ - drivers/media/rc/keymaps/rc-avermedia-cardbus.c | 2 +- - drivers/media/rc/keymaps/rc-imon-mce.c | 2 +- - drivers/media/rc/keymaps/rc-imon-pad.c | 6 +- - .../media/rc/keymaps/rc-kworld-plus-tv-analog.c | 2 +- - drivers/media/rc/keymaps/rc-rc6-mce.c | 4 +- - drivers/media/rc/keymaps/rc-tivo.c | 98 ++++++++++++++++++++ - drivers/media/rc/mceusb.c | 16 +++- - drivers/media/rc/nuvoton-cir.c | 62 ++++++++++--- - drivers/media/rc/nuvoton-cir.h | 17 +++- - drivers/staging/lirc/lirc_sasem.c | 13 ++- - include/linux/input.h | 5 +- - include/media/rc-map.h | 2 + - 24 files changed, 439 insertions(+), 87 deletions(-) - -diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig -index 2560f01..30a8cfd 100644 ---- a/drivers/hid/Kconfig -+++ b/drivers/hid/Kconfig -@@ -492,6 +492,12 @@ config SMARTJOYPLUS_FF - Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to - enable force feedback support for it. - -+config HID_TIVO_SLIDE -+ tristate "TiVo Slide Bluetooth remote control support" -+ depends on USB_HID -+ ---help--- -+ Say Y if you have a TiVo Slide Bluetooth remote control. -+ - config HID_TOPSEED - tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" - depends on USB_HID -diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile -index 6efc2a0..7c1efa3 100644 ---- a/drivers/hid/Makefile -+++ b/drivers/hid/Makefile -@@ -66,6 +66,7 @@ obj-$(CONFIG_HID_STANTUM) += hid-stantum.o - obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o - obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o - obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o -+obj-$(CONFIG_HID_TIVO) += hid-tivo.o - obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o - obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o - obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 92a0d61..8ece9eb 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -533,6 +533,9 @@ - - #define USB_VENDOR_ID_THRUSTMASTER 0x044f - -+#define USB_VENDOR_ID_TIVO 0x150a -+#define USB_DEVICE_ID_TIVO_SLIDE 0x1201 -+ - #define USB_VENDOR_ID_TOPSEED 0x0766 - #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 - -diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c -index 7f552bf..88d4703 100644 ---- a/drivers/hid/hid-input.c -+++ b/drivers/hid/hid-input.c -@@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = { - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, -- 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, -+ 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, - unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, -- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, -+ unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk - }; -@@ -365,6 +365,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - case 0x1: map_key_clear(KEY_POWER); break; - case 0x2: map_key_clear(KEY_SLEEP); break; - case 0x3: map_key_clear(KEY_WAKEUP); break; -+ case 0x4: map_key_clear(KEY_CONTEXT_MENU); break; -+ case 0x5: map_key_clear(KEY_MENU); break; -+ case 0x6: map_key_clear(KEY_PROG1); break; -+ case 0x7: map_key_clear(KEY_HELP); break; -+ case 0x8: map_key_clear(KEY_EXIT); break; -+ case 0x9: map_key_clear(KEY_SELECT); break; -+ case 0xa: map_key_clear(KEY_RIGHT); break; -+ case 0xb: map_key_clear(KEY_LEFT); break; -+ case 0xc: map_key_clear(KEY_UP); break; -+ case 0xd: map_key_clear(KEY_DOWN); break; -+ case 0xe: map_key_clear(KEY_POWER2); break; -+ case 0xf: map_key_clear(KEY_RESTART); break; - default: goto unknown; - } - break; -@@ -474,16 +486,39 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - } - break; - -- case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ -+ case HID_UP_CONSUMER: /* USB HUT v1.12, pages 75-84 */ - switch (usage->hid & HID_USAGE) { - case 0x000: goto ignore; -+ case 0x030: map_key_clear(KEY_POWER); break; -+ case 0x031: map_key_clear(KEY_RESTART); break; -+ case 0x032: map_key_clear(KEY_SLEEP); break; - case 0x034: map_key_clear(KEY_SLEEP); break; -+ case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE); break; - case 0x036: map_key_clear(BTN_MISC); break; - -- case 0x040: map_key_clear(KEY_MENU); break; -- case 0x045: map_key_clear(KEY_RADIO); break; -- -+ case 0x040: map_key_clear(KEY_MENU); break; /* Menu */ -+ case 0x041: map_key_clear(KEY_SELECT); break; /* Menu Pick */ -+ case 0x042: map_key_clear(KEY_UP); break; /* Menu Up */ -+ case 0x043: map_key_clear(KEY_DOWN); break; /* Menu Down */ -+ case 0x044: map_key_clear(KEY_LEFT); break; /* Menu Left */ -+ case 0x045: map_key_clear(KEY_RIGHT); break; /* Menu Right */ -+ case 0x046: map_key_clear(KEY_ESC); break; /* Menu Escape */ -+ case 0x047: map_key_clear(KEY_KPPLUS); break; /* Menu Value Increase */ -+ case 0x048: map_key_clear(KEY_KPMINUS); break; /* Menu Value Decrease */ -+ -+ case 0x060: map_key_clear(KEY_INFO); break; /* Data On Screen */ -+ case 0x061: map_key_clear(KEY_SUBTITLE); break; /* Closed Caption */ -+ case 0x063: map_key_clear(KEY_VCR); break; /* VCR/TV */ -+ case 0x065: map_key_clear(KEY_CAMERA); break; /* Snapshot */ -+ case 0x069: map_key_clear(KEY_RED); break; -+ case 0x06a: map_key_clear(KEY_GREEN); break; -+ case 0x06b: map_key_clear(KEY_BLUE); break; -+ case 0x06c: map_key_clear(KEY_YELLOW); break; -+ case 0x06d: map_key_clear(KEY_ZOOM); break; -+ -+ case 0x082: map_key_clear(KEY_VIDEO_NEXT); break; - case 0x083: map_key_clear(KEY_LAST); break; -+ case 0x084: map_key_clear(KEY_ENTER); break; - case 0x088: map_key_clear(KEY_PC); break; - case 0x089: map_key_clear(KEY_TV); break; - case 0x08a: map_key_clear(KEY_WWW); break; -@@ -517,6 +552,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - case 0x0b7: map_key_clear(KEY_STOPCD); break; - case 0x0b8: map_key_clear(KEY_EJECTCD); break; - case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break; -+ case 0x0b9: map_key_clear(KEY_SHUFFLE); break; -+ case 0x0bf: map_key_clear(KEY_SLOW); break; - - case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; - case 0x0e0: map_abs_clear(ABS_VOLUME); break; -@@ -524,6 +561,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - case 0x0e5: map_key_clear(KEY_BASSBOOST); break; - case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; - case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; -+ case 0x0f5: map_key_clear(KEY_SLOW); break; - - case 0x182: map_key_clear(KEY_BOOKMARKS); break; - case 0x183: map_key_clear(KEY_CONFIG); break; -@@ -540,6 +578,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - case 0x18e: map_key_clear(KEY_CALENDAR); break; - case 0x191: map_key_clear(KEY_FINANCE); break; - case 0x192: map_key_clear(KEY_CALC); break; -+ case 0x193: map_key_clear(KEY_PLAYER); break; - case 0x194: map_key_clear(KEY_FILE); break; - case 0x196: map_key_clear(KEY_WWW); break; - case 0x199: map_key_clear(KEY_CHAT); break; -@@ -548,8 +587,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - case 0x1a6: map_key_clear(KEY_HELP); break; - case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; - case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; -- case 0x1b6: map_key_clear(KEY_MEDIA); break; -- case 0x1b7: map_key_clear(KEY_SOUND); break; -+ case 0x1ae: map_key_clear(KEY_KEYBOARD); break; -+ case 0x1b6: map_key_clear(KEY_IMAGES); break; -+ case 0x1b7: map_key_clear(KEY_AUDIO); break; -+ case 0x1b8: map_key_clear(KEY_VIDEO); break; - case 0x1bc: map_key_clear(KEY_MESSENGER); break; - case 0x1bd: map_key_clear(KEY_INFO); break; - case 0x201: map_key_clear(KEY_NEW); break; -@@ -578,7 +619,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel - case 0x233: map_key_clear(KEY_SCROLLUP); break; - case 0x234: map_key_clear(KEY_SCROLLDOWN); break; - case 0x238: map_rel(REL_HWHEEL); break; -+ case 0x23d: map_key_clear(KEY_EDIT); break; - case 0x25f: map_key_clear(KEY_CANCEL); break; -+ case 0x269: map_key_clear(KEY_INSERT); break; -+ case 0x26a: map_key_clear(KEY_DELETE); break; - case 0x279: map_key_clear(KEY_REDO); break; - - case 0x289: map_key_clear(KEY_REPLY); break; -diff --git a/drivers/hid/hid-tivo.c b/drivers/hid/hid-tivo.c -new file mode 100644 -index 0000000..3d43c06 ---- /dev/null -+++ b/drivers/hid/hid-tivo.c -@@ -0,0 +1,89 @@ -+/* -+ * HID driver for TiVo Slide Bluetooth remote -+ * -+ * Copyright (c) 2011 Jarod Wilson -+ * based on the hid-topseed driver, which is in turn, based on hid-cherry... -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the Free -+ * Software Foundation; either version 2 of the License, or (at your option) -+ * any later version. -+ */ -+ -+#include -+#include -+#include -+ -+#include "hid-ids.h" -+ -+#define HID_UP_TIVOVENDOR 0xffff0000 -+#define tivo_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ -+ EV_KEY, (c)) -+ -+static int tivo_input_mapping(struct hid_device *hdev, struct hid_input *hi, -+ struct hid_field *field, struct hid_usage *usage, -+ unsigned long **bit, int *max) -+{ -+ switch (usage->hid & HID_USAGE_PAGE) { -+ case HID_UP_TIVOVENDOR: -+ switch (usage->hid & HID_USAGE) { -+ /* TiVo button */ -+ case 0x3d: tivo_map_key_clear(KEY_MEDIA); break; -+ /* Live TV */ -+ case 0x3e: tivo_map_key_clear(KEY_TV); break; -+ /* Red thumbs down */ -+ case 0x41: tivo_map_key_clear(KEY_KPMINUS); break; -+ /* Green thumbs up */ -+ case 0x42: tivo_map_key_clear(KEY_KPPLUS); break; -+ default: -+ return 0; -+ } -+ break; -+ case HID_UP_CONSUMER: -+ switch (usage->hid & HID_USAGE) { -+ /* Enter/Last (default mapping: KEY_LAST) */ -+ case 0x083: tivo_map_key_clear(KEY_ENTER); break; -+ /* Info (default mapping: KEY_PROPS) */ -+ case 0x209: tivo_map_key_clear(KEY_INFO); break; -+ default: -+ return 0; -+ } -+ break; -+ default: -+ return 0; -+ } -+ -+ /* This means we found a matching mapping here, else, look in the -+ * standard hid mappings in hid-input.c */ -+ return 1; -+} -+ -+static const struct hid_device_id tivo_devices[] = { -+ /* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */ -+ { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, -+ { } -+}; -+MODULE_DEVICE_TABLE(hid, tivo_devices); -+ -+static struct hid_driver tivo_driver = { -+ .name = "tivo_slide", -+ .id_table = tivo_devices, -+ .input_mapping = tivo_input_mapping, -+}; -+ -+static int __init tivo_init(void) -+{ -+ return hid_register_driver(&tivo_driver); -+} -+ -+static void __exit tivo_exit(void) -+{ -+ hid_unregister_driver(&tivo_driver); -+} -+ -+module_init(tivo_init); -+module_exit(tivo_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jarod Wilson "); -diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c -index 956f7ae..4c2a689 100644 ---- a/drivers/media/dvb/dvb-usb/dibusb-common.c -+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c -@@ -408,7 +408,7 @@ struct rc_map_table rc_map_dibusb_table[] = { - - { 0x8008, KEY_DVD }, - { 0x8009, KEY_AUDIO }, -- { 0x800a, KEY_MEDIA }, /* Pictures */ -+ { 0x800a, KEY_IMAGES }, /* Pictures */ - { 0x800b, KEY_VIDEO }, - - { 0x800c, KEY_BACK }, -diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c -index da9dc91..51bfd42 100644 ---- a/drivers/media/dvb/dvb-usb/m920x.c -+++ b/drivers/media/dvb/dvb-usb/m920x.c -@@ -632,9 +632,9 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { - { 0x16, KEY_POWER }, - { 0x17, KEY_FAVORITES }, - { 0x0f, KEY_TEXT }, -- { 0x48, KEY_MEDIA }, /* preview */ -+ { 0x48, KEY_PROGRAM }, /* preview */ - { 0x1c, KEY_EPG }, -- { 0x04, KEY_LIST }, /* record list */ -+ { 0x04, KEY_LIST }, /* record list */ - { 0x03, KEY_1 }, - { 0x01, KEY_2 }, - { 0x06, KEY_3 }, -@@ -674,14 +674,14 @@ static struct rc_map_table rc_map_pinnacle310e_table[] = { - { 0x0e, KEY_MUTE }, - /* { 0x49, KEY_LR }, */ /* L/R */ - { 0x07, KEY_SLEEP }, /* Hibernate */ -- { 0x08, KEY_MEDIA }, /* A/V */ -- { 0x0e, KEY_MENU }, /* Recall */ -+ { 0x08, KEY_VIDEO }, /* A/V */ -+ { 0x0e, KEY_MENU }, /* Recall */ - { 0x45, KEY_ZOOMIN }, - { 0x46, KEY_ZOOMOUT }, -- { 0x18, KEY_TV }, /* Red */ -- { 0x53, KEY_VCR }, /* Green */ -- { 0x5e, KEY_SAT }, /* Yellow */ -- { 0x5f, KEY_PLAYER }, /* Blue */ -+ { 0x18, KEY_RED }, /* Red */ -+ { 0x53, KEY_GREEN }, /* Green */ -+ { 0x5e, KEY_YELLOW }, /* Yellow */ -+ { 0x5f, KEY_BLUE }, /* Blue */ - }; - - /* DVB USB Driver stuff */ -diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c -index 9d3cd2d..bc350e9 100644 ---- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c -+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c -@@ -47,7 +47,7 @@ static struct rc_map_table rc_map_haupp_table[] = { - { 0x1e17, KEY_RIGHT }, - { 0x1e18, KEY_VIDEO }, - { 0x1e19, KEY_AUDIO }, -- { 0x1e1a, KEY_MEDIA }, -+ { 0x1e1a, KEY_IMAGES }, - { 0x1e1b, KEY_EPG }, - { 0x1e1c, KEY_TV }, - { 0x1e1e, KEY_NEXT }, -diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c -index a05007c..235ac72 100644 ---- a/drivers/media/dvb/frontends/drx397xD.c -+++ b/drivers/media/dvb/frontends/drx397xD.c -@@ -17,7 +17,6 @@ - * along with this program; If not, see . - */ - --#define DEBUG /* uncomment if you want debugging output */ - #include - #include - #include -diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c -index cbe2f0d..420bb42 100644 ---- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c -+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c -@@ -52,7 +52,7 @@ - my TTUSB, so let it undef'd unless you want to implement another - frontend. never tested. - -- DEBUG: -+ debug: - define it to > 3 for really hardcore debugging. you probably don't want - this unless the device doesn't load at all. > 2 for bandwidth statistics. - */ -@@ -134,20 +134,19 @@ struct ttusb { - /* ugly workaround ... don't know why it's necessary to read */ - /* all result codes. */ - --#define DEBUG 0 - static int ttusb_cmd(struct ttusb *ttusb, - const u8 * data, int len, int needresult) - { - int actual_len; - int err; --#if DEBUG >= 3 - int i; - -- printk(">"); -- for (i = 0; i < len; ++i) -- printk(" %02x", data[i]); -- printk("\n"); --#endif -+ if (debug >= 3) { -+ printk(KERN_DEBUG ">"); -+ for (i = 0; i < len; ++i) -+ printk(KERN_CONT " %02x", data[i]); -+ printk(KERN_CONT "\n"); -+ } - - if (mutex_lock_interruptible(&ttusb->semusb) < 0) - return -EAGAIN; -@@ -176,13 +175,15 @@ static int ttusb_cmd(struct ttusb *ttusb, - mutex_unlock(&ttusb->semusb); - return err; - } --#if DEBUG >= 3 -- actual_len = ttusb->last_result[3] + 4; -- printk("<"); -- for (i = 0; i < actual_len; ++i) -- printk(" %02x", ttusb->last_result[i]); -- printk("\n"); --#endif -+ -+ if (debug >= 3) { -+ actual_len = ttusb->last_result[3] + 4; -+ printk(KERN_DEBUG "<"); -+ for (i = 0; i < actual_len; ++i) -+ printk(KERN_CONT " %02x", ttusb->last_result[i]); -+ printk(KERN_CONT "\n"); -+ } -+ - if (!needresult) - mutex_unlock(&ttusb->semusb); - return 0; -@@ -636,16 +637,13 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) - ++ttusb->mux_state; - else { - ttusb->mux_state = 0; --#if DEBUG > 3 -- if (ttusb->insync) -- printk("%02x ", data[-1]); --#else - if (ttusb->insync) { -- printk("%s: lost sync.\n", -+ dprintk("%s: %02x\n", -+ __func__, data[-1]); -+ printk(KERN_INFO "%s: lost sync.\n", - __func__); - ttusb->insync = 0; - } --#endif - } - break; - case 3: -@@ -744,6 +742,9 @@ static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) - static void ttusb_iso_irq(struct urb *urb) - { - struct ttusb *ttusb = urb->context; -+ struct usb_iso_packet_descriptor *d; -+ u8 *data; -+ int len, i; - - if (!ttusb->iso_streaming) - return; -@@ -755,21 +756,14 @@ static void ttusb_iso_irq(struct urb *urb) - #endif - - if (!urb->status) { -- int i; - for (i = 0; i < urb->number_of_packets; ++i) { -- struct usb_iso_packet_descriptor *d; -- u8 *data; -- int len; - numpkt++; - if (time_after_eq(jiffies, lastj + HZ)) { --#if DEBUG > 2 -- printk -- ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n", -- numpkt * HZ / (jiffies - lastj), -- numts, numstuff, numsec, numinvalid, -- numts + numstuff + numsec + -- numinvalid); --#endif -+ dprintk("frames/s: %lu (ts: %d, stuff %d, " -+ "sec: %d, invalid: %d, all: %d)\n", -+ numpkt * HZ / (jiffies - lastj), -+ numts, numstuff, numsec, numinvalid, -+ numts + numstuff + numsec + numinvalid); - numts = numstuff = numsec = numinvalid = 0; - lastj = jiffies; - numpkt = 0; -diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile -index 85cac7d..8c0cb70 100644 ---- a/drivers/media/rc/keymaps/Makefile -+++ b/drivers/media/rc/keymaps/Makefile -@@ -2,6 +2,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-alink-dtu-m.o \ - rc-anysee.o \ - rc-apac-viewcomp.o \ -+ rc-apple.o \ - rc-asus-pc39.o \ - rc-ati-tv-wonder-hd-600.o \ - rc-avermedia-a16d.o \ -@@ -77,6 +78,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-terratec-cinergy-xs.o \ - rc-terratec-slim.o \ - rc-tevii-nec.o \ -+ rc-tivo.o \ - rc-total-media-in-hand.o \ - rc-trekstor.o \ - rc-tt-1500.o \ -diff --git a/drivers/media/rc/keymaps/rc-apple.c b/drivers/media/rc/keymaps/rc-apple.c -new file mode 100644 -index 0000000..9fff474 ---- /dev/null -+++ b/drivers/media/rc/keymaps/rc-apple.c -@@ -0,0 +1,55 @@ -+/* rc-apple.c - Keytable for Apple remotes -+ * -+ * Copyright (c) 2011 by Jarod Wilson -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+ -+/* -+ * The Apple remotes use an NEC-ish protocol, but instead of having a -+ * command/not_command pair, they use a vendor ID of 0x77e1. Another byte -+ * is used for a pairing ID (0-255), to make it possible to have a system -+ * listen for only its specific remote. The last byte is the actual command -+ * byte. This table will only Just Work(tm) with remotes that have their -+ * pairing byte set to 0xc7 at the moment (one of my Apple remotes), but -+ * it can be trivially replaced from userspace with one using a different -+ * pairing byte value. -+ */ -+static struct rc_map_table apple[] = { -+ { 0x77e150c7, KEY_VOLUMEUP }, -+ { 0x77e130c7, KEY_VOLUMEDOWN }, -+ { 0x77e190c7, KEY_REWIND }, -+ { 0x77e160c7, KEY_FASTFORWARD }, -+ { 0x77e1a0c7, KEY_PLAYPAUSE }, -+ { 0x77e1c0c7, KEY_MENU }, -+}; -+ -+static struct rc_map_list apple_map = { -+ .map = { -+ .scan = apple, -+ .size = ARRAY_SIZE(apple), -+ .rc_type = RC_TYPE_NEC, -+ .name = RC_MAP_APPLE, -+ } -+}; -+ -+static int __init init_rc_map_apple(void) -+{ -+ return rc_map_register(&apple_map); -+} -+ -+static void __exit exit_rc_map_apple(void) -+{ -+ rc_map_unregister(&apple_map); -+} -+ -+module_init(init_rc_map_apple) -+module_exit(exit_rc_map_apple) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jarod Wilson "); -diff --git a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c -index bdf97b7..22f54d4 100644 ---- a/drivers/media/rc/keymaps/rc-avermedia-cardbus.c -+++ b/drivers/media/rc/keymaps/rc-avermedia-cardbus.c -@@ -52,7 +52,7 @@ static struct rc_map_table avermedia_cardbus[] = { - { 0x28, KEY_SELECT }, /* Select */ - { 0x29, KEY_BLUE }, /* Blue/Picture */ - { 0x2a, KEY_BACKSPACE }, /* Back */ -- { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ -+ { 0x2b, KEY_VIDEO }, /* PIP (Picture-in-picture) */ - { 0x2c, KEY_DOWN }, - { 0x2e, KEY_DOT }, - { 0x2f, KEY_TV }, /* Live TV */ -diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c -index 937a819..0ea2aa1 100644 ---- a/drivers/media/rc/keymaps/rc-imon-mce.c -+++ b/drivers/media/rc/keymaps/rc-imon-mce.c -@@ -111,7 +111,7 @@ static struct rc_map_table imon_mce[] = { - { 0x800ff44d, KEY_TITLE }, - - { 0x800ff40c, KEY_POWER }, -- { 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */ -+ { 0x800ff40d, KEY_MEDIA }, /* Windows MCE button */ - - }; - -diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c -index 63d42bd..75d3843 100644 ---- a/drivers/media/rc/keymaps/rc-imon-pad.c -+++ b/drivers/media/rc/keymaps/rc-imon-pad.c -@@ -87,7 +87,7 @@ static struct rc_map_table imon_pad[] = { - - { 0x2b8515b7, KEY_VIDEO }, - { 0x299195b7, KEY_AUDIO }, -- { 0x2ba115b7, KEY_CAMERA }, -+ { 0x2ba115b7, KEY_IMAGES }, - { 0x28a515b7, KEY_TV }, - { 0x29a395b7, KEY_DVD }, - { 0x29a295b7, KEY_DVD }, -@@ -97,7 +97,7 @@ static struct rc_map_table imon_pad[] = { - { 0x2ba395b7, KEY_MENU }, - - { 0x288515b7, KEY_BOOKMARKS }, -- { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ -+ { 0x2ab715b7, KEY_CAMERA }, /* Thumbnail */ - { 0x298595b7, KEY_SUBTITLE }, - { 0x2b8595b7, KEY_LANGUAGE }, - -@@ -125,7 +125,7 @@ static struct rc_map_table imon_pad[] = { - { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ - { 0x02000065, KEY_COMPOSE }, /* RightMenu */ - { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ -- { 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */ -+ { 0x2ab195b7, KEY_MEDIA }, /* Go or MultiMon */ - { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ - }; - -diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c -index 08d1831..7fa17a3 100644 ---- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c -+++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c -@@ -17,7 +17,7 @@ - */ - - static struct rc_map_table kworld_plus_tv_analog[] = { -- { 0x0c, KEY_LEFTMETA }, /* Kworld key */ -+ { 0x0c, KEY_MEDIA }, /* Kworld key */ - { 0x16, KEY_CLOSECD }, /* -> ) */ - { 0x1d, KEY_POWER2 }, - -diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c -index 8dd519e..01b69bc 100644 ---- a/drivers/media/rc/keymaps/rc-rc6-mce.c -+++ b/drivers/media/rc/keymaps/rc-rc6-mce.c -@@ -30,7 +30,7 @@ static struct rc_map_table rc6_mce[] = { - { 0x800f040a, KEY_DELETE }, - { 0x800f040b, KEY_ENTER }, - { 0x800f040c, KEY_POWER }, /* PC Power */ -- { 0x800f040d, KEY_LEFTMETA }, /* Windows MCE button */ -+ { 0x800f040d, KEY_MEDIA }, /* Windows MCE button */ - { 0x800f040e, KEY_MUTE }, - { 0x800f040f, KEY_INFO }, - -@@ -87,7 +87,7 @@ static struct rc_map_table rc6_mce[] = { - - { 0x800f0465, KEY_POWER2 }, /* TV Power */ - { 0x800f046e, KEY_PLAYPAUSE }, -- { 0x800f046f, KEY_MEDIA }, /* Start media application (NEW) */ -+ { 0x800f046f, KEY_PLAYER }, /* Start media application (NEW) */ - - { 0x800f0480, KEY_BRIGHTNESSDOWN }, - { 0x800f0481, KEY_PLAYPAUSE }, -diff --git a/drivers/media/rc/keymaps/rc-tivo.c b/drivers/media/rc/keymaps/rc-tivo.c -new file mode 100644 -index 0000000..98ad085 ---- /dev/null -+++ b/drivers/media/rc/keymaps/rc-tivo.c -@@ -0,0 +1,98 @@ -+/* rc-tivo.c - Keytable for TiVo remotes -+ * -+ * Copyright (c) 2011 by Jarod Wilson -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+ -+/* -+ * Initial mapping is for the TiVo remote included in the Nero LiquidTV bundle, -+ * which also ships with a TiVo-branded IR transceiver, supported by the mceusb -+ * driver. Note that the remote uses an NEC-ish protocol, but instead of having -+ * a command/not_command pair, it has a vendor ID of 0xa10c, but some keys, the -+ * NEC extended checksums do pass, so the table presently has the intended -+ * values and the checksum-passed versions for those keys. -+ */ -+static struct rc_map_table tivo[] = { -+ { 0xa10c900f, KEY_MEDIA }, /* TiVo Button */ -+ { 0xa10c0807, KEY_POWER2 }, /* TV Power */ -+ { 0xa10c8807, KEY_TV }, /* Live TV/Swap */ -+ { 0xa10c2c03, KEY_VIDEO_NEXT }, /* TV Input */ -+ { 0xa10cc807, KEY_INFO }, -+ { 0xa10cfa05, KEY_CYCLEWINDOWS }, /* Window */ -+ { 0x0085305f, KEY_CYCLEWINDOWS }, -+ { 0xa10c6c03, KEY_EPG }, /* Guide */ -+ -+ { 0xa10c2807, KEY_UP }, -+ { 0xa10c6807, KEY_DOWN }, -+ { 0xa10ce807, KEY_LEFT }, -+ { 0xa10ca807, KEY_RIGHT }, -+ -+ { 0xa10c1807, KEY_SCROLLDOWN }, /* Red Thumbs Down */ -+ { 0xa10c9807, KEY_SELECT }, -+ { 0xa10c5807, KEY_SCROLLUP }, /* Green Thumbs Up */ -+ -+ { 0xa10c3807, KEY_VOLUMEUP }, -+ { 0xa10cb807, KEY_VOLUMEDOWN }, -+ { 0xa10cd807, KEY_MUTE }, -+ { 0xa10c040b, KEY_RECORD }, -+ { 0xa10c7807, KEY_CHANNELUP }, -+ { 0xa10cf807, KEY_CHANNELDOWN }, -+ { 0x0085301f, KEY_CHANNELDOWN }, -+ -+ { 0xa10c840b, KEY_PLAY }, -+ { 0xa10cc40b, KEY_PAUSE }, -+ { 0xa10ca40b, KEY_SLOW }, -+ { 0xa10c440b, KEY_REWIND }, -+ { 0xa10c240b, KEY_FASTFORWARD }, -+ { 0xa10c640b, KEY_PREVIOUS }, -+ { 0xa10ce40b, KEY_NEXT }, /* ->| */ -+ -+ { 0xa10c220d, KEY_ZOOM }, /* Aspect */ -+ { 0xa10c120d, KEY_STOP }, -+ { 0xa10c520d, KEY_DVD }, /* DVD Menu */ -+ -+ { 0xa10c140b, KEY_NUMERIC_1 }, -+ { 0xa10c940b, KEY_NUMERIC_2 }, -+ { 0xa10c540b, KEY_NUMERIC_3 }, -+ { 0xa10cd40b, KEY_NUMERIC_4 }, -+ { 0xa10c340b, KEY_NUMERIC_5 }, -+ { 0xa10cb40b, KEY_NUMERIC_6 }, -+ { 0xa10c740b, KEY_NUMERIC_7 }, -+ { 0xa10cf40b, KEY_NUMERIC_8 }, -+ { 0x0085302f, KEY_NUMERIC_8 }, -+ { 0xa10c0c03, KEY_NUMERIC_9 }, -+ { 0xa10c8c03, KEY_NUMERIC_0 }, -+ { 0xa10ccc03, KEY_ENTER }, -+ { 0xa10c4c03, KEY_CLEAR }, -+}; -+ -+static struct rc_map_list tivo_map = { -+ .map = { -+ .scan = tivo, -+ .size = ARRAY_SIZE(tivo), -+ .rc_type = RC_TYPE_NEC, -+ .name = RC_MAP_TIVO, -+ } -+}; -+ -+static int __init init_rc_map_tivo(void) -+{ -+ return rc_map_register(&tivo_map); -+} -+ -+static void __exit exit_rc_map_tivo(void) -+{ -+ rc_map_unregister(&tivo_map); -+} -+ -+module_init(init_rc_map_tivo) -+module_exit(exit_rc_map_tivo) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jarod Wilson "); -diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c -index 044fb7a..47a1c5d 100644 ---- a/drivers/media/rc/mceusb.c -+++ b/drivers/media/rc/mceusb.c -@@ -149,6 +149,8 @@ enum mceusb_model_type { - POLARIS_EVK, - CX_HYBRID_TV, - MULTIFUNCTION, -+ TIVO_KIT, -+ MCE_GEN2_NO_TX, - }; - - struct mceusb_model { -@@ -172,6 +174,10 @@ static const struct mceusb_model mceusb_model[] = { - [MCE_GEN2] = { - .mce_gen2 = 1, - }, -+ [MCE_GEN2_NO_TX] = { -+ .mce_gen2 = 1, -+ .no_tx = 1, -+ }, - [MCE_GEN2_TX_INV] = { - .mce_gen2 = 1, - .tx_mask_normal = 1, -@@ -197,6 +203,10 @@ static const struct mceusb_model mceusb_model[] = { - .mce_gen2 = 1, - .ir_intfnum = 2, - }, -+ [TIVO_KIT] = { -+ .mce_gen2 = 1, -+ .rc_map = RC_MAP_TIVO, -+ }, - }; - - static struct usb_device_id mceusb_dev_table[] = { -@@ -230,6 +230,8 @@ static struct usb_device_id mceusb_dev_table[] = { - { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, - /* Philips/Spinel plus IR transceiver for ASUS */ - { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, -+ /* Philips IR transceiver (Dell branded) */ -+ { USB_DEVICE(VENDOR_PHILIPS, 0x2093) }, - /* Realtek MCE IR Receiver and card reader */ - { USB_DEVICE(VENDOR_REALTEK, 0x0161), - .driver_info = MULTIFUNCTION }, -@@ -279,7 +289,8 @@ static struct usb_device_id mceusb_dev_table[] = { - /* Formosa21 / eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, - /* Formosa aim / Trust MCE Infrared Receiver */ -- { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe017), -+ .driver_info = MCE_GEN2_NO_TX }, - /* Formosa Industrial Computing / Beanbag Emulation Device */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, - /* Formosa21 / eHome Infrared Receiver */ -@@ -308,7 +319,8 @@ static struct usb_device_id mceusb_dev_table[] = { - /* Northstar Systems, Inc. eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, - /* TiVo PC IR Receiver */ -- { USB_DEVICE(VENDOR_TIVO, 0x2000) }, -+ { USB_DEVICE(VENDOR_TIVO, 0x2000), -+ .driver_info = TIVO_KIT }, - /* Conexant Hybrid TV "Shelby" Polaris SDK */ - { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), - .driver_info = POLARIS_EVK }, -diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c -index d4d6449..5d93384 100644 ---- a/drivers/media/rc/nuvoton-cir.c -+++ b/drivers/media/rc/nuvoton-cir.c -@@ -37,8 +37,6 @@ - - #include "nuvoton-cir.h" - --static char *chip_id = "w836x7hg"; -- - /* write val to config reg */ - static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) - { -@@ -233,6 +231,8 @@ static int nvt_hw_detect(struct nvt_dev *nvt) - unsigned long flags; - u8 chip_major, chip_minor; - int ret = 0; -+ char chip_id[12]; -+ bool chip_unknown = false; - - nvt_efm_enable(nvt); - -@@ -246,15 +246,39 @@ static int nvt_hw_detect(struct nvt_dev *nvt) - } - - chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); -- nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); - -- if (chip_major != CHIP_ID_HIGH || -- (chip_minor != CHIP_ID_LOW && chip_minor != CHIP_ID_LOW2)) { -- nvt_pr(KERN_ERR, "%s: unsupported chip, id: 0x%02x 0x%02x", -- chip_id, chip_major, chip_minor); -- ret = -ENODEV; -+ /* these are the known working chip revisions... */ -+ switch (chip_major) { -+ case CHIP_ID_HIGH_667: -+ strcpy(chip_id, "w83667hg\0"); -+ if (chip_minor != CHIP_ID_LOW_667) -+ chip_unknown = true; -+ break; -+ case CHIP_ID_HIGH_677B: -+ strcpy(chip_id, "w83677hg\0"); -+ if (chip_minor != CHIP_ID_LOW_677B2 && -+ chip_minor != CHIP_ID_LOW_677B3) -+ chip_unknown = true; -+ break; -+ case CHIP_ID_HIGH_677C: -+ strcpy(chip_id, "w83677hg-c\0"); -+ if (chip_minor != CHIP_ID_LOW_677C) -+ chip_unknown = true; -+ break; -+ default: -+ strcpy(chip_id, "w836x7hg\0"); -+ chip_unknown = true; -+ break; - } - -+ /* warn, but still let the driver load, if we don't know this chip */ -+ if (chip_unknown) -+ nvt_pr(KERN_WARNING, "%s: unknown chip, id: 0x%02x 0x%02x, " -+ "it may not work...", chip_id, chip_major, chip_minor); -+ else -+ nvt_dbg("%s: chip id: 0x%02x 0x%02x", -+ chip_id, chip_major, chip_minor); -+ - nvt_efm_disable(nvt); - - spin_lock_irqsave(&nvt->nvt_lock, flags); -@@ -267,13 +291,23 @@ static int nvt_hw_detect(struct nvt_dev *nvt) - - static void nvt_cir_ldev_init(struct nvt_dev *nvt) - { -- u8 val; -+ u8 val, psreg, psmask, psval; -+ -+ if (nvt->chip_major == CHIP_ID_HIGH_667) { -+ psreg = CR_MULTIFUNC_PIN_SEL; -+ psmask = MULTIFUNC_PIN_SEL_MASK; -+ psval = MULTIFUNC_ENABLE_CIR | MULTIFUNC_ENABLE_CIRWB; -+ } else { -+ psreg = CR_OUTPUT_PIN_SEL; -+ psmask = OUTPUT_PIN_SEL_MASK; -+ psval = OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB; -+ } - -- /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ -- val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); -- val &= OUTPUT_PIN_SEL_MASK; -- val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); -- nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); -+ /* output pin selection: enable CIR, with WB sensor enabled */ -+ val = nvt_cr_read(nvt, psreg); -+ val &= psmask; -+ val |= psval; -+ nvt_cr_write(nvt, val, psreg); - - /* Select CIR logical device and enable */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -@@ -674,7 +674,7 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) - rawir.pulse ? "pulse" : "space", - rawir.duration); - -- ir_raw_event_store(nvt->rdev, &rawir); -+ ir_raw_event_store_with_filter(nvt->rdev, &rawir); - } - - /* -@@ -1110,12 +1110,12 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) - rdev->input_id.version = nvt->chip_minor; - rdev->driver_name = NVT_DRIVER_NAME; - rdev->map_name = RC_MAP_RC6_MCE; -+ rdev->timeout = US_TO_NS(1000); -+ /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ -+ rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); - #if 0 - rdev->min_timeout = XYZ; - rdev->max_timeout = XYZ; -- rdev->timeout = XYZ; -- /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ -- rdev->rx_resolution = XYZ; - /* tx bits */ - rdev->tx_resolution = XYZ; - #endif -diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h -index 048135e..379795d 100644 ---- a/drivers/media/rc/nuvoton-cir.h -+++ b/drivers/media/rc/nuvoton-cir.h -@@ -330,9 +330,13 @@ struct nvt_dev { - #define EFER_EFM_DISABLE 0xaa - - /* Chip IDs found in CR_CHIP_ID_{HI,LO} */ --#define CHIP_ID_HIGH 0xb4 --#define CHIP_ID_LOW 0x72 --#define CHIP_ID_LOW2 0x73 -+#define CHIP_ID_HIGH_667 0xa5 -+#define CHIP_ID_HIGH_677B 0xb4 -+#define CHIP_ID_HIGH_677C 0xc3 -+#define CHIP_ID_LOW_667 0x13 -+#define CHIP_ID_LOW_677B2 0x72 -+#define CHIP_ID_LOW_677B3 0x73 -+#define CHIP_ID_LOW_677C 0x33 - - /* Config regs we need to care about */ - #define CR_SOFTWARE_RESET 0x02 -@@ -341,6 +345,7 @@ struct nvt_dev { - #define CR_CHIP_ID_LO 0x21 - #define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ - #define CR_OUTPUT_PIN_SEL 0x27 -+#define CR_MULTIFUNC_PIN_SEL 0x2c - #define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ - /* next three regs valid for both the CIR and CIR_WAKE logical devices */ - #define CR_CIR_BASE_ADDR_HI 0x60 -@@ -364,10 +369,16 @@ struct nvt_dev { - #define CIR_INTR_MOUSE_IRQ_BIT 0x80 - #define PME_INTR_CIR_PASS_BIT 0x08 - -+/* w83677hg CIR pin config */ - #define OUTPUT_PIN_SEL_MASK 0xbc - #define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ - #define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ - -+/* w83667hg CIR pin config */ -+#define MULTIFUNC_PIN_SEL_MASK 0x1f -+#define MULTIFUNC_ENABLE_CIR 0x80 /* Pin75=CIRRX, Pin76=CIRTX1 */ -+#define MULTIFUNC_ENABLE_CIRWB 0x20 /* enable wide-band sensor */ -+ - /* MCE CIR signal length, related on sample period */ - - /* MCE CIR controller signal length: about 43ms -diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c -index 63a438d..7080cde 100644 ---- a/drivers/staging/lirc/lirc_sasem.c -+++ b/drivers/staging/lirc/lirc_sasem.c -@@ -570,6 +570,7 @@ static void incoming_packet(struct sasem_context *context, - unsigned char *buf = urb->transfer_buffer; - long ms; - struct timeval tv; -+ int i; - - if (len != 8) { - printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n", -@@ -577,12 +578,12 @@ static void incoming_packet(struct sasem_context *context, - return; - } - --#ifdef DEBUG -- int i; -- for (i = 0; i < 8; ++i) -- printk(KERN_INFO "%02x ", buf[i]); -- printk(KERN_INFO "\n"); --#endif -+ if (debug) { -+ printk(KERN_INFO "Incoming data: "); -+ for (i = 0; i < 8; ++i) -+ printk(KERN_CONT "%02x ", buf[i]); -+ printk(KERN_CONT "\n"); -+ } - - /* - * Lirc could deal with the repeat code, but we really need to block it -diff --git a/include/linux/input.h b/include/linux/input.h -index e428382..be082e9 100644 ---- a/include/linux/input.h -+++ b/include/linux/input.h -@@ -553,8 +553,8 @@ struct input_keymap_entry { - #define KEY_DVD 0x185 /* Media Select DVD */ - #define KEY_AUX 0x186 - #define KEY_MP3 0x187 --#define KEY_AUDIO 0x188 --#define KEY_VIDEO 0x189 -+#define KEY_AUDIO 0x188 /* AL Audio Browser */ -+#define KEY_VIDEO 0x189 /* AL Movie Browser */ - #define KEY_DIRECTORY 0x18a - #define KEY_LIST 0x18b - #define KEY_MEMO 0x18c /* Media Select Messages */ -@@ -605,6 +605,7 @@ struct input_keymap_entry { - #define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ - #define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ - #define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ -+#define KEY_IMAGES 0x1ba /* AL Image Browser */ - - #define KEY_DEL_EOL 0x1c0 - #define KEY_DEL_EOS 0x1c1 -diff --git a/include/media/rc-map.h b/include/media/rc-map.h -index 9184751..b2bd405 100644 ---- a/include/media/rc-map.h -+++ b/include/media/rc-map.h -@@ -58,6 +58,7 @@ void rc_map_init(void); - #define RC_MAP_ALINK_DTU_M "rc-alink-dtu-m" - #define RC_MAP_ANYSEE "rc-anysee" - #define RC_MAP_APAC_VIEWCOMP "rc-apac-viewcomp" -+#define RC_MAP_APPLE "rc-apple" - #define RC_MAP_ASUS_PC39 "rc-asus-pc39" - #define RC_MAP_ATI_TV_WONDER_HD_600 "rc-ati-tv-wonder-hd-600" - #define RC_MAP_AVERMEDIA_A16D "rc-avermedia-a16d" -@@ -136,6 +137,7 @@ void rc_map_init(void); - #define RC_MAP_TERRATEC_CINERGY_XS "rc-terratec-cinergy-xs" - #define RC_MAP_TERRATEC_SLIM "rc-terratec-slim" - #define RC_MAP_TEVII_NEC "rc-tevii-nec" -+#define RC_MAP_TIVO "rc-tivo" - #define RC_MAP_TOTAL_MEDIA_IN_HAND "rc-total-media-in-hand" - #define RC_MAP_TREKSTOR "rc-trekstor" - #define RC_MAP_TT_1500 "rc-tt-1500" -diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c -index accaf6c..43908a7 100644 ---- a/drivers/media/rc/ite-cir.c -+++ b/drivers/media/rc/ite-cir.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - #include - #include - #include - diff --git a/linux-2.6-v4l-dvb-update.patch b/linux-2.6-v4l-dvb-update.patch index 0984884e9..e69de29bb 100644 --- a/linux-2.6-v4l-dvb-update.patch +++ b/linux-2.6-v4l-dvb-update.patch @@ -1,7725 +0,0 @@ -v4l/dvb/rc media_tree updates from 2.6.39 - -commit f9d088784131609419595b51beb701d0f3aa6afc -Author: Jarod Wilson -Date: Tue Mar 22 17:23:15 2011 -0300 - - [media] rc: interim support for 32-bit NEC-ish scancodes - - The Apple and TiVo remotes I've got use an NEC-ish protocol, but rather - than a command/not_command pair, they have what appear to be vendor ID - bytes. This change makes the NEC decoder warn if the command/not_command - checksum fails, but then passes along a full 32-bit scancode for keymap - lookup. This change should make no difference for existing keymaps, - since they simply won't have 32-bit scancodes, but allows for a 32-bit - keymap. At the moment, that'll have to be uploaded by the user, but I've - got Apple and TiVo remote keymaps forthcoming. - - In the long run (2.6.40, hopefully), we should probably just always use - all 32 bits for all NEC keymaps, but this should get us by for 2.6.39. - - (Note that a few of the TiVo keys actuallly *do* pass the command - checksum, so for now, the keymap for this remote will have to be a mix - of 24-bit and 32-bit scancodes, but so be it). - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 4568844fff1dc46b8adb7364ac3a844aa34d1e38 -Author: Jarod Wilson -Date: Fri Mar 4 20:20:47 2011 -0300 - - [media] mceusb: topseed 0x0011 needs gen3 init for tx to work - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 514c3ef0671bdbdb1ae3708c63cce12e6f4b55f0 -Author: Jarod Wilson -Date: Fri Mar 4 19:53:05 2011 -0300 - - [media] lirc_zilog: error out if buffer read bytes != chunk size - - Give it a few tries, then exit. Prevents a possible endless loop - situation. - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 7f72453889801675b825083d7ebddc341ccbb331 -Author: Jarod Wilson -Date: Fri Mar 4 17:57:24 2011 -0300 - - [media] lirc: silence some compile warnings - - Both lirc_imon and lirc_sasem were causing gcc to complain about the - possible use of uninitialized variables. - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 37bda6318295a3412e191f1a5cb5a5bea2db59a5 -Author: Jarod Wilson -Date: Fri Mar 4 17:31:11 2011 -0300 - - [media] hdpvr: use same polling interval as other OS - - The hdpvr's IR part, in short, sucks. As observed with a usb traffic - sniffer, the Windows software for it uses a polling interval of 405ms. - Its still not behaving as well as I'd like even with this change, but - this inches us closer and closer to that point... - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 6ba973db97845b0b7322d1a0cd5348d3024d7387 -Author: Jarod Wilson -Date: Fri Mar 4 17:30:17 2011 -0300 - - [media] ir-kbd-i2c: pass device code w/key in hauppauge case - - The new hauppauge key tables use both device code button code. - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 246286a63b4820c1c039a836025c52ec79d18a2f -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 22:23:08 2011 -0300 - - [media] rc/keymaps: Remove the obsolete rc-rc5-tv keymap - - This keymap were used for the Hauppauge Black remote controller - only. It also contains some keycodes not found there. As the - Hauppauge Black is now part of the hauppauge keymap, just remove - it. - - Also, remove the modprobe hacks to select between the Gray - and the Black versions of the remote controller as: - - Both are supported by default by the keymap; - - If the user just wants one keyboard supported, - it is just a matter of changing the keymap via - the userspace tool (ir-keytable), removing - the keys that he doesn't desire. As ir-keytable - auto-loads the keys via udev, this is better than - obscure modprobe parameters. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit af2a42cc5eec9659bac301885ac795be81d019c8 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:48 2011 -0300 - - [media] remove the old RC_MAP_HAUPPAUGE_NEW RC map - - The rc-hauppauge-new map is a messy thing, as it bundles 3 - - different remote controllers as if they were just one, - discarding the address byte. Also, some key maps are wrong. - - With the conversion to the new rc-core, it is likely that - most of the devices won't be working properly, as the i2c - driver and the raw decoders are now providing 16 bits for - the remote, instead of just 8. - - delete mode 100644 drivers/media/rc/keymaps/rc-hauppauge-new.c - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 1ef571252ec29a8b3674deb746bfaa8ad1b034c3 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:47 2011 -0300 - - [media] rc/keymaps: Rename Hauppauge table as rc-hauppauge - - There are two "hauppauge-new" keymaps, one with protocol - unknown, and the other with the protocol marked accordingly. - However, both tables are miss-named. - - Also, the old rc-hauppauge-new is broken, as it mixes - three different controllers as if they were just one. - - This patch solves half of the problem by renaming the - correct keycode table as just rc-hauppauge. This table - contains the codes for the four different types of - remote controllers found on Hauppauge cards, properly - mapped with their different addresses. - - create mode 100644 drivers/media/rc/keymaps/rc-hauppauge.c - delete mode 100644 drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c - [Jarod: fix up RC_MAP_HAUPPAUGE defines] - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 41abb2ee0ac34ecd8769b2ddd84caf67414ca0f7 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:45 2011 -0300 - - [media] rc-rc5-hauppauge-new: Fix Hauppauge Grey mapping - - The keys for the old black were messed with the ones for the - hauppauge grey. Fix it. - - Also, fixes some keycodes and order the keys according with - the way they appear inside the remote controller. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 80daad9d9ece3bbfd0f7cc13dbefc92e3ebb1f6f -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:44 2011 -0300 - - [media] rc-rc5-hauppauge-new: Add support for the old Black RC - - Hans borrowed me an old Black Hauppauge RC. Thanks to that, we - can fix the RC5 table for Hauppauge. - - Thanks-to: Hans Verkuil - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 9ba542ee399a091a56711d5bc1f778f39768a26d -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:43 2011 -0300 - - [media] rc-rc5-hauppauge-new: Add the old control to the table - - Adds the old grey remote controller to Hauppauge table. - - Hans borrowed me an old gray Hauppauge RC. Thanks to that, we - can fix the RC5 table for Hauppauge. - - Thanks-to: Hans Verkuil - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 8d198df40f2d6fe2bfb3b8818dce974b40a614e9 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:43 2011 -0300 - - [media] rc-winfast: Fix the keycode tables - - One of the remotes has a picture available at: - http://lirc.sourceforge.net/remotes/leadtek/Y04G0004.jpg - - As there's one variant with a set direction keys plus vol/chann - keys, and the same table is used for both models, change it to - represent all keys, avoiding the usage of weird function keys. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 434e6519a292096ee29303d74688ced038606842 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:42 2011 -0300 - - [media] a800: Fix a few wrong IR key assignments - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 674ff915ca5d7b40d710eb910afcf7f490b76ab0 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:41 2011 -0300 - - [media] opera1: Use multimedia keys instead of an app-specific mapping - - This driver uses an app-specific keymap for one of the tables. This - is wrong. Instead, use the standard keycodes. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit d59b1eedf5d5108cc90b9cfaf17f7845bad4f806 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:40 2011 -0300 - - [media] dw2102: Use multimedia keys instead of an app-specific mapping - - This driver uses an app-specific keymap for one of the tables. This - is wrong. Instead, use the standard keycodes. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 651cef86ff15697ad8a5659ecc9bc43f16ca07ba -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:39 2011 -0300 - - [media] rc/keymaps: Use KEY_LEFTMETA were pertinent - - Using xev and testing the "Windows" key on a normal keyboard, it - is mapped as KEY_LEFTMETA. So, as this is the standard code for - it, use it, instead of a generic, meaningless KEY_PROG1. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit bb8aeecec52791eacc727d8400ced9e1b230ec49 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:38 2011 -0300 - - [media] rc/keymaps: Fix most KEY_PROG[n] keycodes - - Those KEY_PROG[n] keys were used on places where the developer - didn't know for sure what key should be used. On several cases, - using KEY_RED, KEY_GREEN, KEY_YELLOW would be enough. On others, - there are specific keys for that already. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit 84c122769cca37480fbcd7de5a102f6221874247 -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:37 2011 -0300 - - [media] rc/keymaps: Use KEY_VIDEO for Video Source - - Each keyboard map were using a different definition for - the Source/Video Source key. - Behold Columbus were the only one using KEY_PROPS. - - As we want to standardize those keys at X11 and at - userspace applications, we need to use just one code - for it. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit ea35a76538a45e78cee889d2c462df71a9b34e4c -Author: Mauro Carvalho Chehab -Date: Mon Jan 24 12:18:36 2011 -0300 - - [media] rc/keymaps: use KEY_CAMERA for snapshots - - On a few places, KEY_MHP were used for snapshots. However, KEY_CAMERA - is used for it on all the other keyboards that have a snapshot/Picture - button. - - Signed-off-by: Mauro Carvalho Chehab - Signed-off-by: Jarod Wilson - -commit d33d27b1745fc72b042b6431dd29ee484fdabbcc -Author: Andy Walls -Date: Thu Feb 17 21:32:06 2011 -0300 - - [media] lirc_zilog: Update TODO list based on work completed and revised plans - - Update the TODO.lirc_zilog based on what has been completed. Also revised - the development plan for lirc_zilog to not try and split Tx/Rx for one IR - transceiver unit between lirc_zilog and ir-kbd-i2c, since that would be a - ref-counting nightmare. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 1a9cb97924e71b33a5d1a59facd58e1a584daa97 -Author: Andy Walls -Date: Thu Feb 17 21:14:13 2011 -0300 - - [media] lirc_zilog: Fix somewhat confusing information messages in ir_probe() - - The total sequence of messages emitted by the ir_porbe() calls - for a transceiver's two i2c_clients was confusing. Clean it up a bit. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit cf141c455938cb245b6bf489c832d0c2e3833686 -Author: Andy Walls -Date: Thu Feb 17 20:50:38 2011 -0300 - - [media] lirc_zilog: Add locking of the i2c_clients when in use - - Lock the i2c_client pointers and prevent i2c_client removal when - lirc_zilog is perfoming a series of operations that require valid - i2c_client pointers. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 6f4276ac6e98a05833aa7e49e438fec198e537e8 -Author: Andy Walls -Date: Mon Feb 7 22:30:55 2011 -0300 - - [media] lirc_zilog: Add ref counting of struct IR, IR_tx, and IR_rx - - This is a major change to add pointer reference counting for - struct IR, struct IR_tx, and struct IR_rx object instances. - This ref counting gets lirc_zilog closer to gracefully handling - bridge drivers and hot-unplugged USB devices disappearing out from - under lirc_zilog when the /dev/lircN node is still open. (mutexes - to protect the i2c_client pointers in struct IR_tx and struct IR_rx - still need to be added.) - - This reference counting also helps lirc_zilog clean up properly - when the i2c_clients disappear. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit f3bc78dbb5942f1827a97329b1c095903329aa8b -Author: Andy Walls -Date: Thu Jan 27 23:02:20 2011 -0300 - - [media] lirc_zilog: Move constants from ir_probe() into the lirc_driver template - - ir_probe() makes a number of constant assignments into the lirc_driver - object after copying in a template. Make better use of the template. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 6f61cb53e2b8f6c65cf2c6b3e3710233c643e6ce -Author: Andy Walls -Date: Thu Jan 27 22:32:44 2011 -0300 - - [media] lirc_zilog: Always allocate a Rx lirc_buffer object - - Always allocate a lirc_buffer object, instead of just upon setup of - the Rx i2c_client. If we do not allocate a lirc_buffer object, because - we are not handling the Rx i2c_client, lirc_dev will allocate its own - lirc_buffer anyway and not tell us about its location. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 8941d66476b33d339408f66898766e0d8ac2cb0a -Author: Andy Walls -Date: Thu Jan 27 02:34:13 2011 -0300 - - [media] lirc_zilog: Remove unneeded rx->buf_lock - - Remove the rx->buf_lock that protected the rx->buf lirc_buffer. The - underlying operations on the objects within the lirc_buffer are already - protected by spinlocks, or the objects are constant (e.g. chunk_size). - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit fa2d70732b5699cd3bc9fc0e82c154e1410857e4 -Author: Andy Walls -Date: Thu Jan 27 02:10:42 2011 -0300 - - [media] lirc_zilog: Don't acquire the rx->buf_lock in the poll() function - - There is no need to take the rx->buf_lock in the the poll() function - as all the underling calls made on objects in the rx->buf lirc_buffer object - are protected by spinlocks. - - Corrected a bad error return value in poll(): return POLLERR instead - of -ENODEV. - - Added some comments to poll() for when, in the future, I forget what - poll() and poll_wait() are supposed to do. - - [Jarod: minor debug spew fix] - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 45a0dd2e9575f72693c94920e8d189ea395d5b5d -Author: Andy Walls -Date: Thu Jan 27 00:04:15 2011 -0300 - - [media] lirc_zilog: Use kernel standard methods for marking device non-seekable - - lirc_zilog had its own llseek stub that returned -ESPIPE. Get rid of - it and use the kernel's no_llseek() and nonseekable_open() functions - instead. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit c4c4362e1e1bd1a39f186b96ba5b0df74470f101 -Author: Andy Walls -Date: Wed Jan 26 22:04:24 2011 -0300 - - [media] lirc_zilog: Convert the instance open count to an atomic_t - - The open count is simply used for deciding if the Rx polling thread - needs to poll the IR chip for userspace. Simplify the manipulation - of the open count by using an atomic_t and not requiring a lock - The polling thread errantly didn't try to take the lock anyway. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 7f94125db5889c202b95e717ccbe9e35de63c14a -Author: Andy Walls -Date: Wed Jan 26 21:48:32 2011 -0300 - - [media] lirc_zilog: Convert ir_device instance array to a linked list - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit d2a47dc2e351e6cf33b98f0d3339d6d39fd8ed8b -Author: Andy Walls -Date: Wed Jan 26 21:25:47 2011 -0300 - - [media] lirc_zilog: Remove broken, ineffective reference counting - - The set_use_inc() and set_use_dec() functions tried to lock - the underlying bridge driver device instance in memory by - changing the use count on the device's i2c_clients. This - worked for PCI devices (ivtv, cx18, bttv). It doesn't - work for hot-pluggable usb devices (pvrusb2 and hdpvr). - With usb device instances, the driver may get locked into - memory, but the unplugged hardware is gone. - - The set_use_inc() set_use_dec() functions also tried to have - lirc_zilog change its own module refernce count, which is - racy and not guaranteed to work. The lirc_dev module does - actually perform proper module ref count manipulation on the - lirc_zilog module, so there is need for lirc_zilog to - attempt a buggy module get on itself anyway. - - lirc_zilog also errantly called these functions on itself - in open() and close(), but lirc_dev did that already too. - - So let's just gut the bodies of the set_use_*() functions, - and remove the extra calls to them from within lirc_zilog. - - Proper reference counting of the struct IR, IR_rx, and IR_tx - objects -- to handle the case when the underlying - bttv, ivtv, cx18, hdpvr, or pvrusb2 bridge driver module or - device instance goes away -- will be added in subsequent - patches. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 767dd925f017bd0f0363f827509cebfaf0bb2b57 -Author: Andy Walls -Date: Wed Jan 26 21:06:43 2011 -0300 - - [media] lirc_zilog: Restore checks for existence of the IR_tx object - - This reverts commit 8090232a237ab62e22307fc060097da1a283dd66 and - adds an additional check for ir->tx == NULL. - - The user may need us to handle an RX only unit. Apparently - there are TV capture units in existence with Rx only wiring - and/or RX only firmware for the on-board Zilog Z8 IR unit. - - Signed-off-by: Andy Walls - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 91f27e09d7bba99341bd8ce035995ae21ff493f7 -Author: Jarod Wilson -Date: Wed Mar 2 13:23:52 2011 -0300 - - [media] hdpvr: i2c master enhancements - - Make the hdpvr's i2c master implementation more closely mirror that of - the pvrusb2 driver. Currently makes no significant difference in IR - reception behavior with ir-kbd-i2c (i.e., it still sucks). - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit c1ba04cf3a0626f725795e3a853654928596d522 -Author: Jarod Wilson -Date: Tue Feb 1 16:27:05 2011 -0300 - - [media] imon: add more panel scancode mappings - - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 9cd4f638d57b01c5d901f73c94b08fad4aa0b295 -Author: Jarod Wilson -Date: Mon Jan 24 18:22:12 2011 -0300 - - [media] docs: fix typo in lirc_device_interface.xml - - Reported-by: Daniel Burr - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 97ad124749a060d8c4f5461111911474db3b555f -Author: Mauro Carvalho Chehab -Date: Tue Mar 22 17:17:56 2011 -0300 - - ite-cir: Fix a breakage caused by my cleanup patch - - Signed-off-by: Mauro Carvalho Chehab - -commit a38fc7a384bd679f2550e2a2323ff3e690d4ffd7 -Author: Juan J. Garcia de Soria -Date: Wed Mar 16 17:14:53 2011 -0300 - - [media] lirc: remove staging lirc_it87 and lirc_ite8709 drivers - - Remove older drivers lirc_it87 and lirc_ite8709 from the LIRC staging area, - since they're now superceded by ite-cir. - - Signed-off-by: Juan J. Garcia de Soria - Tested-by: Stephan Raue - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit e1bede3475c792a5c4793ec3cc929efa24aaae64 -Author: Mauro Carvalho Chehab -Date: Tue Mar 22 15:12:40 2011 -0300 - - [media] ite-cir: Fix some CodingStyle issues - - Cc: Juan J. Garcia de Soria - Cc: Stephan Raue - Cc: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - -commit 9e8739744ccc917011a91e489339278d7bb14eac -Author: Juan J. Garcia de Soria -Date: Wed Mar 16 17:14:52 2011 -0300 - - [media] rc: New rc-based ite-cir driver for several ITE CIRs - - This is a second version of an rc-core based driver for the ITE Tech IT8712F - CIR and now for a pair of other variants of the IT8512 CIR too. - - This driver should replace the lirc_it87 and lirc_ite8709 currently living in - the LIRC staging directory. - - The driver should support the ITE8704, ITE8713, ITE8708 and ITE8709 (this last - one yet untested) PNP ID's. - - The code doesn'te reuse code from the pre-existing LIRC drivers, but has been - written from scratch using the nuvoton.cir driver as a skeleton. - - This new driver shouldn't exhibit timing problems when running under load (or - with interrupts disabled for relatively long times). It works OOTB with the - RC6 MCE remote bundled with the ASUS EEEBox. TX support is implemented, but - I'm unable to test it since my hardware lacks TX capability. - - Signed-off-by: Juan J. Garcia de Soria - Tested-by: Stephan Raue - Signed-off-by: Jarod Wilson - Signed-off-by: Mauro Carvalho Chehab - .../DocBook/v4l/lirc_device_interface.xml | 2 +- - drivers/media/dvb/dvb-usb/a800.c | 8 +- - drivers/media/dvb/dvb-usb/digitv.c | 2 +- - drivers/media/dvb/dvb-usb/dw2102.c | 40 +- - drivers/media/dvb/dvb-usb/opera1.c | 33 +- - drivers/media/dvb/siano/sms-cards.c | 2 +- - drivers/media/dvb/ttpci/budget-ci.c | 15 +- - drivers/media/rc/Kconfig | 13 + - drivers/media/rc/Makefile | 1 + - drivers/media/rc/imon.c | 11 +- - drivers/media/rc/ir-nec-decoder.c | 10 +- - drivers/media/rc/ite-cir.c | 1736 ++++++++++++++++++++ - drivers/media/rc/ite-cir.h | 481 ++++++ - drivers/media/rc/keymaps/Makefile | 4 +- - drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c | 6 +- - drivers/media/rc/keymaps/rc-avermedia-dvbt.c | 4 +- - drivers/media/rc/keymaps/rc-avermedia-m135a.c | 2 +- - .../media/rc/keymaps/rc-avermedia-m733a-rm-k6.c | 2 +- - drivers/media/rc/keymaps/rc-avermedia-rm-ks.c | 2 +- - drivers/media/rc/keymaps/rc-behold-columbus.c | 2 +- - drivers/media/rc/keymaps/rc-behold.c | 2 +- - drivers/media/rc/keymaps/rc-budget-ci-old.c | 3 +- - drivers/media/rc/keymaps/rc-cinergy.c | 2 +- - drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c | 2 +- - drivers/media/rc/keymaps/rc-encore-enltv.c | 4 +- - drivers/media/rc/keymaps/rc-encore-enltv2.c | 2 +- - drivers/media/rc/keymaps/rc-flydvb.c | 4 +- - drivers/media/rc/keymaps/rc-hauppauge-new.c | 100 -- - drivers/media/rc/keymaps/rc-hauppauge.c | 241 +++ - drivers/media/rc/keymaps/rc-imon-mce.c | 2 +- - drivers/media/rc/keymaps/rc-imon-pad.c | 2 +- - drivers/media/rc/keymaps/rc-kworld-315u.c | 2 +- - .../media/rc/keymaps/rc-kworld-plus-tv-analog.c | 2 +- - drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c | 2 +- - drivers/media/rc/keymaps/rc-nebula.c | 2 +- - drivers/media/rc/keymaps/rc-norwood.c | 2 +- - drivers/media/rc/keymaps/rc-pctv-sedna.c | 2 +- - drivers/media/rc/keymaps/rc-pixelview-mk12.c | 2 +- - drivers/media/rc/keymaps/rc-pixelview-new.c | 2 +- - drivers/media/rc/keymaps/rc-pixelview.c | 2 +- - drivers/media/rc/keymaps/rc-pv951.c | 4 +- - drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c | 141 -- - drivers/media/rc/keymaps/rc-rc5-tv.c | 81 - - drivers/media/rc/keymaps/rc-rc6-mce.c | 2 +- - .../media/rc/keymaps/rc-real-audio-220-32-keys.c | 2 +- - drivers/media/rc/keymaps/rc-winfast.c | 22 +- - drivers/media/rc/mceusb.c | 4 +- - drivers/media/video/cx18/cx18-i2c.c | 2 +- - drivers/media/video/cx23885/cx23885-input.c | 2 +- - drivers/media/video/cx88/cx88-input.c | 4 +- - drivers/media/video/em28xx/em28xx-cards.c | 10 +- - drivers/media/video/hdpvr/hdpvr-i2c.c | 72 +- - drivers/media/video/ir-kbd-i2c.c | 18 +- - drivers/media/video/ivtv/ivtv-i2c.c | 5 +- - drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 4 +- - drivers/media/video/saa7134/saa7134-input.c | 2 +- - drivers/staging/lirc/Kconfig | 12 - - drivers/staging/lirc/Makefile | 2 - - drivers/staging/lirc/TODO.lirc_zilog | 51 +- - drivers/staging/lirc/lirc_imon.c | 2 +- - drivers/staging/lirc/lirc_it87.c | 1027 ------------ - drivers/staging/lirc/lirc_it87.h | 116 -- - drivers/staging/lirc/lirc_ite8709.c | 542 ------ - drivers/staging/lirc/lirc_sasem.c | 2 +- - drivers/staging/lirc/lirc_zilog.c | 814 ++++++---- - include/media/rc-map.h | 4 +- - include/media/soc_camera.h | 2 + - 67 files changed, 3128 insertions(+), 2513 deletions(-) - ---- -diff --git a/Documentation/DocBook/v4l/lirc_device_interface.xml b/Documentation/DocBook/v4l/lirc_device_interface.xml -index 68134c0..0e0453f 100644 ---- a/Documentation/DocBook/v4l/lirc_device_interface.xml -+++ b/Documentation/DocBook/v4l/lirc_device_interface.xml -@@ -45,7 +45,7 @@ describing an IR signal are read from the chardev. - The data written to the chardev is a pulse/space sequence of integer - values. Pulses and spaces are only marked implicitly by their position. The - data must start and end with a pulse, therefore, the data must always include --an unevent number of samples. The write function must block until the data has -+an uneven number of samples. The write function must block until the data has - been transmitted by the hardware. - - -diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c -index 53b93a4..f8e9bf1 100644 ---- a/drivers/media/dvb/dvb-usb/a800.c -+++ b/drivers/media/dvb/dvb-usb/a800.c -@@ -38,8 +38,8 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr - } - - static struct rc_map_table rc_map_a800_table[] = { -- { 0x0201, KEY_PROG1 }, /* SOURCE */ -- { 0x0200, KEY_POWER }, /* POWER */ -+ { 0x0201, KEY_MODE }, /* SOURCE */ -+ { 0x0200, KEY_POWER2 }, /* POWER */ - { 0x0205, KEY_1 }, /* 1 */ - { 0x0206, KEY_2 }, /* 2 */ - { 0x0207, KEY_3 }, /* 3 */ -@@ -52,8 +52,8 @@ static struct rc_map_table rc_map_a800_table[] = { - { 0x0212, KEY_LEFT }, /* L / DISPLAY */ - { 0x0211, KEY_0 }, /* 0 */ - { 0x0213, KEY_RIGHT }, /* R / CH RTN */ -- { 0x0217, KEY_PROG2 }, /* SNAP SHOT */ -- { 0x0210, KEY_PROG3 }, /* 16-CH PREV */ -+ { 0x0217, KEY_CAMERA }, /* SNAP SHOT */ -+ { 0x0210, KEY_LAST }, /* 16-CH PREV */ - { 0x021e, KEY_VOLUMEDOWN }, /* VOL DOWN */ - { 0x020c, KEY_ZOOM }, /* FULL SCREEN */ - { 0x021f, KEY_VOLUMEUP }, /* VOL UP */ -diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c -index f2dbce7..f6344cd 100644 ---- a/drivers/media/dvb/dvb-usb/digitv.c -+++ b/drivers/media/dvb/dvb-usb/digitv.c -@@ -176,7 +176,7 @@ static struct rc_map_table rc_map_digitv_table[] = { - { 0xaf59, KEY_AUX }, - { 0x5f5a, KEY_DVD }, - { 0x6f5a, KEY_POWER }, -- { 0x9f5a, KEY_MHP }, /* labelled 'Picture' */ -+ { 0x9f5a, KEY_CAMERA }, /* labelled 'Picture' */ - { 0xaf5a, KEY_AUDIO }, - { 0x5f65, KEY_INFO }, - { 0x6f65, KEY_F13 }, /* 16:9 */ -diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c -index 98cf302..f5b9da1 100644 ---- a/drivers/media/dvb/dvb-usb/dw2102.c -+++ b/drivers/media/dvb/dvb-usb/dw2102.c -@@ -1224,8 +1224,8 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap) - } - - static struct rc_map_table rc_map_dw210x_table[] = { -- { 0xf80a, KEY_Q }, /*power*/ -- { 0xf80c, KEY_M }, /*mute*/ -+ { 0xf80a, KEY_POWER2 }, /*power*/ -+ { 0xf80c, KEY_MUTE }, /*mute*/ - { 0xf811, KEY_1 }, - { 0xf812, KEY_2 }, - { 0xf813, KEY_3 }, -@@ -1236,25 +1236,25 @@ static struct rc_map_table rc_map_dw210x_table[] = { - { 0xf818, KEY_8 }, - { 0xf819, KEY_9 }, - { 0xf810, KEY_0 }, -- { 0xf81c, KEY_PAGEUP }, /*ch+*/ -- { 0xf80f, KEY_PAGEDOWN }, /*ch-*/ -- { 0xf81a, KEY_O }, /*vol+*/ -- { 0xf80e, KEY_Z }, /*vol-*/ -- { 0xf804, KEY_R }, /*rec*/ -- { 0xf809, KEY_D }, /*fav*/ -- { 0xf808, KEY_BACKSPACE }, /*rewind*/ -- { 0xf807, KEY_A }, /*fast*/ -- { 0xf80b, KEY_P }, /*pause*/ -- { 0xf802, KEY_ESC }, /*cancel*/ -- { 0xf803, KEY_G }, /*tab*/ -+ { 0xf81c, KEY_CHANNELUP }, /*ch+*/ -+ { 0xf80f, KEY_CHANNELDOWN }, /*ch-*/ -+ { 0xf81a, KEY_VOLUMEUP }, /*vol+*/ -+ { 0xf80e, KEY_VOLUMEDOWN }, /*vol-*/ -+ { 0xf804, KEY_RECORD }, /*rec*/ -+ { 0xf809, KEY_FAVORITES }, /*fav*/ -+ { 0xf808, KEY_REWIND }, /*rewind*/ -+ { 0xf807, KEY_FASTFORWARD }, /*fast*/ -+ { 0xf80b, KEY_PAUSE }, /*pause*/ -+ { 0xf802, KEY_ESC }, /*cancel*/ -+ { 0xf803, KEY_TAB }, /*tab*/ - { 0xf800, KEY_UP }, /*up*/ -- { 0xf81f, KEY_ENTER }, /*ok*/ -- { 0xf801, KEY_DOWN }, /*down*/ -- { 0xf805, KEY_C }, /*cap*/ -- { 0xf806, KEY_S }, /*stop*/ -- { 0xf840, KEY_F }, /*full*/ -- { 0xf81e, KEY_W }, /*tvmode*/ -- { 0xf81b, KEY_B }, /*recall*/ -+ { 0xf81f, KEY_OK }, /*ok*/ -+ { 0xf801, KEY_DOWN }, /*down*/ -+ { 0xf805, KEY_CAMERA }, /*cap*/ -+ { 0xf806, KEY_STOP }, /*stop*/ -+ { 0xf840, KEY_ZOOM }, /*full*/ -+ { 0xf81e, KEY_TV }, /*tvmode*/ -+ { 0xf81b, KEY_LAST }, /*recall*/ - }; - - static struct rc_map_table rc_map_tevii_table[] = { -diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c -index 1f1b7d6..7e569f4 100644 ---- a/drivers/media/dvb/dvb-usb/opera1.c -+++ b/drivers/media/dvb/dvb-usb/opera1.c -@@ -342,23 +342,22 @@ static struct rc_map_table rc_map_opera1_table[] = { - {0x49b6, KEY_8}, - {0x05fa, KEY_9}, - {0x45ba, KEY_0}, -- {0x09f6, KEY_UP}, /*chanup */ -- {0x1be5, KEY_DOWN}, /*chandown */ -- {0x5da3, KEY_LEFT}, /*voldown */ -- {0x5fa1, KEY_RIGHT}, /*volup */ -- {0x07f8, KEY_SPACE}, /*tab */ -- {0x1fe1, KEY_ENTER}, /*play ok */ -- {0x1be4, KEY_Z}, /*zoom */ -- {0x59a6, KEY_M}, /*mute */ -- {0x5ba5, KEY_F}, /*tv/f */ -- {0x19e7, KEY_R}, /*rec */ -- {0x01fe, KEY_S}, /*Stop */ -- {0x03fd, KEY_P}, /*pause */ -- {0x03fc, KEY_W}, /*<- -> */ -- {0x07f9, KEY_C}, /*capture */ -- {0x47b9, KEY_Q}, /*exit */ -- {0x43bc, KEY_O}, /*power */ -- -+ {0x09f6, KEY_CHANNELUP}, /*chanup */ -+ {0x1be5, KEY_CHANNELDOWN}, /*chandown */ -+ {0x5da3, KEY_VOLUMEDOWN}, /*voldown */ -+ {0x5fa1, KEY_VOLUMEUP}, /*volup */ -+ {0x07f8, KEY_SPACE}, /*tab */ -+ {0x1fe1, KEY_OK}, /*play ok */ -+ {0x1be4, KEY_ZOOM}, /*zoom */ -+ {0x59a6, KEY_MUTE}, /*mute */ -+ {0x5ba5, KEY_RADIO}, /*tv/f */ -+ {0x19e7, KEY_RECORD}, /*rec */ -+ {0x01fe, KEY_STOP}, /*Stop */ -+ {0x03fd, KEY_PAUSE}, /*pause */ -+ {0x03fc, KEY_SCREEN}, /*<- -> */ -+ {0x07f9, KEY_CAMERA}, /*capture */ -+ {0x47b9, KEY_ESC}, /*exit */ -+ {0x43bc, KEY_POWER2}, /*power */ - }; - - static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state) -diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c -index 25b43e5..af121db 100644 ---- a/drivers/media/dvb/siano/sms-cards.c -+++ b/drivers/media/dvb/siano/sms-cards.c -@@ -64,7 +64,7 @@ static struct sms_board sms_boards[] = { - .type = SMS_NOVA_B0, - .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", -- .rc_codes = RC_MAP_RC5_HAUPPAUGE_NEW, -+ .rc_codes = RC_MAP_HAUPPAUGE, - .board_cfg.leds_power = 26, - .board_cfg.led0 = 27, - .board_cfg.led1 = 28, -diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c -index b82756d..1d79ada 100644 ---- a/drivers/media/dvb/ttpci/budget-ci.c -+++ b/drivers/media/dvb/ttpci/budget-ci.c -@@ -26,7 +26,7 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - * - * -- * the project's page is at http://www.linuxtv.org/ -+ * the project's page is at http://www.linuxtv.org/ - */ - - #include -@@ -102,6 +102,7 @@ struct budget_ci_ir { - int rc5_device; - u32 ir_key; - bool have_command; -+ bool full_rc5; /* Outputs a full RC5 code */ - }; - - struct budget_ci { -@@ -154,11 +155,18 @@ static void msp430_ir_interrupt(unsigned long data) - return; - budget_ci->ir.have_command = false; - -- /* FIXME: We should generate complete scancodes with device info */ - if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && - budget_ci->ir.rc5_device != (command & 0x1f)) - return; - -+ if (budget_ci->ir.full_rc5) { -+ rc_keydown(dev, -+ budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key, -+ (command & 0x20) ? 1 : 0); -+ return; -+ } -+ -+ /* FIXME: We should generate complete scancodes for all devices */ - rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0); - } - -@@ -206,7 +214,8 @@ static int msp430_ir_init(struct budget_ci *budget_ci) - case 0x1011: - case 0x1012: - /* The hauppauge keymap is a superset of these remotes */ -- dev->map_name = RC_MAP_HAUPPAUGE_NEW; -+ dev->map_name = RC_MAP_HAUPPAUGE; -+ budget_ci->ir.full_rc5 = true; - - if (rc5_device < 0) - budget_ci->ir.rc5_device = 0x1f; -diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig -index 1143845..7f03142 100644 ---- a/drivers/media/rc/Kconfig -+++ b/drivers/media/rc/Kconfig -@@ -135,6 +135,19 @@ config IR_MCEUSB - To compile this driver as a module, choose M here: the - module will be called mceusb. - -+config IR_ITE_CIR -+ tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver" -+ depends on PNP -+ depends on RC_CORE -+ ---help--- -+ Say Y here to enable support for integrated infrared receivers -+ /transceivers made by ITE Tech Inc. These are found in -+ several ASUS devices, like the ASUS Digimatrix or the ASUS -+ EEEBox 1501U. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called ite-cir. -+ - config IR_NUVOTON - tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" - depends on PNP -diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile -index 67b4f7f..c6cfe70 100644 ---- a/drivers/media/rc/Makefile -+++ b/drivers/media/rc/Makefile -@@ -14,6 +14,7 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o - - # stand-alone IR receivers/transmitters - obj-$(CONFIG_IR_IMON) += imon.o -+obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o - obj-$(CONFIG_IR_MCEUSB) += mceusb.o - obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o - obj-$(CONFIG_IR_ENE) += ene_ir.o -diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c -index e7dc6b4..f714e1a 100644 ---- a/drivers/media/rc/imon.c -+++ b/drivers/media/rc/imon.c -@@ -277,12 +277,21 @@ static const struct { - u64 hw_code; - u32 keycode; - } imon_panel_key_table[] = { -- { 0x000000000f00ffeell, KEY_PROG1 }, /* Go */ -+ { 0x000000000f00ffeell, KEY_MEDIA }, /* Go */ -+ { 0x000000001200ffeell, KEY_UP }, -+ { 0x000000001300ffeell, KEY_DOWN }, -+ { 0x000000001400ffeell, KEY_LEFT }, -+ { 0x000000001500ffeell, KEY_RIGHT }, -+ { 0x000000001600ffeell, KEY_ENTER }, -+ { 0x000000001700ffeell, KEY_ESC }, - { 0x000000001f00ffeell, KEY_AUDIO }, - { 0x000000002000ffeell, KEY_VIDEO }, - { 0x000000002100ffeell, KEY_CAMERA }, - { 0x000000002700ffeell, KEY_DVD }, - { 0x000000002300ffeell, KEY_TV }, -+ { 0x000000002b00ffeell, KEY_EXIT }, -+ { 0x000000002c00ffeell, KEY_SELECT }, -+ { 0x000000002d00ffeell, KEY_MENU }, - { 0x000000000500ffeell, KEY_PREVIOUS }, - { 0x000000000700ffeell, KEY_REWIND }, - { 0x000000000400ffeell, KEY_STOP }, -diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c -index 7b58b4a..63ee722 100644 ---- a/drivers/media/rc/ir-nec-decoder.c -+++ b/drivers/media/rc/ir-nec-decoder.c -@@ -49,6 +49,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) - struct nec_dec *data = &dev->raw->nec; - u32 scancode; - u8 address, not_address, command, not_command; -+ bool send_32bits = false; - - if (!(dev->raw->enabled_protocols & RC_TYPE_NEC)) - return 0; -@@ -164,10 +165,15 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev) - if ((command ^ not_command) != 0xff) { - IR_dprintk(1, "NEC checksum error: received 0x%08x\n", - data->bits); -- break; -+ send_32bits = true; - } - -- if ((address ^ not_address) != 0xff) { -+ if (send_32bits) { -+ /* NEC transport, but modified protocol, used by at -+ * least Apple and TiVo remotes */ -+ scancode = data->bits; -+ IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode); -+ } else if ((address ^ not_address) != 0xff) { - /* Extended NEC */ - scancode = address << 16 | - not_address << 8 | -diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c -new file mode 100644 -index 0000000..9be6a83 ---- /dev/null -+++ b/drivers/media/rc/ite-cir.c -@@ -0,0 +1,1736 @@ -+/* -+ * Driver for ITE Tech Inc. IT8712F/IT8512 CIR -+ * -+ * Copyright (C) 2010 Juan Jesús García de Soria -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ * USA. -+ * -+ * Inspired by the original lirc_it87 and lirc_ite8709 drivers, on top of the -+ * skeleton provided by the nuvoton-cir driver. -+ * -+ * The lirc_it87 driver was originally written by Hans-Gunter Lutke Uphues -+ * in 2001, with enhancements by Christoph Bartelmus -+ * , Andrew Calkin and James Edwards -+ * . -+ * -+ * The lirc_ite8709 driver was written by Grégory Lardière -+ * in 2008. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ite-cir.h" -+ -+/* module parameters */ -+ -+/* debug level */ -+static int debug; -+module_param(debug, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Enable debugging output"); -+ -+/* low limit for RX carrier freq, Hz, 0 for no RX demodulation */ -+static int rx_low_carrier_freq; -+module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, " -+ "0 for no RX demodulation"); -+ -+/* high limit for RX carrier freq, Hz, 0 for no RX demodulation */ -+static int rx_high_carrier_freq; -+module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, " -+ "Hz, 0 for no RX demodulation"); -+ -+/* override tx carrier frequency */ -+static int tx_carrier_freq; -+module_param(tx_carrier_freq, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(tx_carrier_freq, "Override TX carrier frequency, Hz"); -+ -+/* override tx duty cycle */ -+static int tx_duty_cycle; -+module_param(tx_duty_cycle, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(tx_duty_cycle, "Override TX duty cycle, 1-100"); -+ -+/* override default sample period */ -+static long sample_period; -+module_param(sample_period, long, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(sample_period, "Override carrier sample period, us"); -+ -+/* override detected model id */ -+static int model_number = -1; -+module_param(model_number, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(model_number, "Use this model number, don't autodetect"); -+ -+ -+/* HW-independent code functions */ -+ -+/* check whether carrier frequency is high frequency */ -+static inline bool ite_is_high_carrier_freq(unsigned int freq) -+{ -+ return freq >= ITE_HCF_MIN_CARRIER_FREQ; -+} -+ -+/* get the bits required to program the carrier frequency in CFQ bits, -+ * unshifted */ -+static u8 ite_get_carrier_freq_bits(unsigned int freq) -+{ -+ if (ite_is_high_carrier_freq(freq)) { -+ if (freq < 425000) -+ return ITE_CFQ_400; -+ -+ else if (freq < 465000) -+ return ITE_CFQ_450; -+ -+ else if (freq < 490000) -+ return ITE_CFQ_480; -+ -+ else -+ return ITE_CFQ_500; -+ } else { -+ /* trim to limits */ -+ if (freq < ITE_LCF_MIN_CARRIER_FREQ) -+ freq = ITE_LCF_MIN_CARRIER_FREQ; -+ if (freq > ITE_LCF_MAX_CARRIER_FREQ) -+ freq = ITE_LCF_MAX_CARRIER_FREQ; -+ -+ /* convert to kHz and subtract the base freq */ -+ freq = -+ DIV_ROUND_CLOSEST(freq - ITE_LCF_MIN_CARRIER_FREQ, -+ 1000); -+ -+ return (u8) freq; -+ } -+} -+ -+/* get the bits required to program the pulse with in TXMPW */ -+static u8 ite_get_pulse_width_bits(unsigned int freq, int duty_cycle) -+{ -+ unsigned long period_ns, on_ns; -+ -+ /* sanitize freq into range */ -+ if (freq < ITE_LCF_MIN_CARRIER_FREQ) -+ freq = ITE_LCF_MIN_CARRIER_FREQ; -+ if (freq > ITE_HCF_MAX_CARRIER_FREQ) -+ freq = ITE_HCF_MAX_CARRIER_FREQ; -+ -+ period_ns = 1000000000UL / freq; -+ on_ns = period_ns * duty_cycle / 100; -+ -+ if (ite_is_high_carrier_freq(freq)) { -+ if (on_ns < 750) -+ return ITE_TXMPW_A; -+ -+ else if (on_ns < 850) -+ return ITE_TXMPW_B; -+ -+ else if (on_ns < 950) -+ return ITE_TXMPW_C; -+ -+ else if (on_ns < 1080) -+ return ITE_TXMPW_D; -+ -+ else -+ return ITE_TXMPW_E; -+ } else { -+ if (on_ns < 6500) -+ return ITE_TXMPW_A; -+ -+ else if (on_ns < 7850) -+ return ITE_TXMPW_B; -+ -+ else if (on_ns < 9650) -+ return ITE_TXMPW_C; -+ -+ else if (on_ns < 11950) -+ return ITE_TXMPW_D; -+ -+ else -+ return ITE_TXMPW_E; -+ } -+} -+ -+/* decode raw bytes as received by the hardware, and push them to the ir-core -+ * layer */ -+static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int -+ length) -+{ -+ u32 sample_period; -+ unsigned long *ldata; -+ unsigned int next_one, next_zero, size; -+ DEFINE_IR_RAW_EVENT(ev); -+ -+ if (length == 0) -+ return; -+ -+ sample_period = dev->params.sample_period; -+ ldata = (unsigned long *)data; -+ size = length << 3; -+ next_one = generic_find_next_le_bit(ldata, size, 0); -+ if (next_one > 0) { -+ ev.pulse = true; -+ ev.duration = -+ ITE_BITS_TO_NS(next_one, sample_period); -+ ir_raw_event_store_with_filter(dev->rdev, &ev); -+ } -+ -+ while (next_one < size) { -+ next_zero = generic_find_next_zero_le_bit(ldata, size, next_one + 1); -+ ev.pulse = false; -+ ev.duration = ITE_BITS_TO_NS(next_zero - next_one, sample_period); -+ ir_raw_event_store_with_filter(dev->rdev, &ev); -+ -+ if (next_zero < size) { -+ next_one = -+ generic_find_next_le_bit(ldata, -+ size, -+ next_zero + 1); -+ ev.pulse = true; -+ ev.duration = -+ ITE_BITS_TO_NS(next_one - next_zero, -+ sample_period); -+ ir_raw_event_store_with_filter -+ (dev->rdev, &ev); -+ } else -+ next_one = size; -+ } -+ -+ ir_raw_event_handle(dev->rdev); -+ -+ ite_dbg_verbose("decoded %d bytes.", length); -+} -+ -+/* set all the rx/tx carrier parameters; this must be called with the device -+ * spinlock held */ -+static void ite_set_carrier_params(struct ite_dev *dev) -+{ -+ unsigned int freq, low_freq, high_freq; -+ int allowance; -+ bool use_demodulator; -+ bool for_tx = dev->transmitting; -+ -+ ite_dbg("%s called", __func__); -+ -+ if (for_tx) { -+ /* we don't need no stinking calculations */ -+ freq = dev->params.tx_carrier_freq; -+ allowance = ITE_RXDCR_DEFAULT; -+ use_demodulator = false; -+ } else { -+ low_freq = dev->params.rx_low_carrier_freq; -+ high_freq = dev->params.rx_high_carrier_freq; -+ -+ if (low_freq == 0) { -+ /* don't demodulate */ -+ freq = -+ ITE_DEFAULT_CARRIER_FREQ; -+ allowance = ITE_RXDCR_DEFAULT; -+ use_demodulator = false; -+ } else { -+ /* calculate the middle freq */ -+ freq = (low_freq + high_freq) / 2; -+ -+ /* calculate the allowance */ -+ allowance = -+ DIV_ROUND_CLOSEST(10000 * (high_freq - low_freq), -+ ITE_RXDCR_PER_10000_STEP -+ * (high_freq + low_freq)); -+ -+ if (allowance < 1) -+ allowance = 1; -+ -+ if (allowance > ITE_RXDCR_MAX) -+ allowance = ITE_RXDCR_MAX; -+ } -+ } -+ -+ /* set the carrier parameters in a device-dependent way */ -+ dev->params.set_carrier_params(dev, ite_is_high_carrier_freq(freq), -+ use_demodulator, ite_get_carrier_freq_bits(freq), allowance, -+ ite_get_pulse_width_bits(freq, dev->params.tx_duty_cycle)); -+} -+ -+/* interrupt service routine for incoming and outgoing CIR data */ -+static irqreturn_t ite_cir_isr(int irq, void *data) -+{ -+ struct ite_dev *dev = data; -+ unsigned long flags; -+ irqreturn_t ret = IRQ_RETVAL(IRQ_NONE); -+ u8 rx_buf[ITE_RX_FIFO_LEN]; -+ int rx_bytes; -+ int iflags; -+ -+ ite_dbg_verbose("%s firing", __func__); -+ -+ /* grab the spinlock */ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* read the interrupt flags */ -+ iflags = dev->params.get_irq_causes(dev); -+ -+ /* check for the receive interrupt */ -+ if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { -+ /* read the FIFO bytes */ -+ rx_bytes = -+ dev->params.get_rx_bytes(dev, rx_buf, -+ ITE_RX_FIFO_LEN); -+ -+ if (rx_bytes > 0) { -+ /* drop the spinlock, since the ir-core layer -+ * may call us back again through -+ * ite_s_idle() */ -+ spin_unlock_irqrestore(&dev-> -+ lock, -+ flags); -+ -+ /* decode the data we've just received */ -+ ite_decode_bytes(dev, rx_buf, -+ rx_bytes); -+ -+ /* reacquire the spinlock */ -+ spin_lock_irqsave(&dev->lock, -+ flags); -+ -+ /* mark the interrupt as serviced */ -+ ret = IRQ_RETVAL(IRQ_HANDLED); -+ } -+ } else if (iflags & ITE_IRQ_TX_FIFO) { -+ /* FIFO space available interrupt */ -+ ite_dbg_verbose("got interrupt for TX FIFO"); -+ -+ /* wake any sleeping transmitter */ -+ wake_up_interruptible(&dev->tx_queue); -+ -+ /* mark the interrupt as serviced */ -+ ret = IRQ_RETVAL(IRQ_HANDLED); -+ } -+ -+ /* drop the spinlock */ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ ite_dbg_verbose("%s done returning %d", __func__, (int)ret); -+ -+ return ret; -+} -+ -+/* set the rx carrier freq range, guess it's in Hz... */ -+static int ite_set_rx_carrier_range(struct rc_dev *rcdev, u32 carrier_low, u32 -+ carrier_high) -+{ -+ unsigned long flags; -+ struct ite_dev *dev = rcdev->priv; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->params.rx_low_carrier_freq = carrier_low; -+ dev->params.rx_high_carrier_freq = carrier_high; -+ ite_set_carrier_params(dev); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return 0; -+} -+ -+/* set the tx carrier freq, guess it's in Hz... */ -+static int ite_set_tx_carrier(struct rc_dev *rcdev, u32 carrier) -+{ -+ unsigned long flags; -+ struct ite_dev *dev = rcdev->priv; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->params.tx_carrier_freq = carrier; -+ ite_set_carrier_params(dev); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return 0; -+} -+ -+/* set the tx duty cycle by controlling the pulse width */ -+static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle) -+{ -+ unsigned long flags; -+ struct ite_dev *dev = rcdev->priv; -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->params.tx_duty_cycle = duty_cycle; -+ ite_set_carrier_params(dev); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return 0; -+} -+ -+/* transmit out IR pulses; what you get here is a batch of alternating -+ * pulse/space/pulse/space lengths that we should write out completely through -+ * the FIFO, blocking on a full FIFO */ -+static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n) -+{ -+ unsigned long flags; -+ struct ite_dev *dev = rcdev->priv; -+ bool is_pulse = false; -+ int remaining_us, fifo_avail, fifo_remaining, last_idx = 0; -+ int max_rle_us, next_rle_us; -+ int ret = n; -+ u8 last_sent[ITE_TX_FIFO_LEN]; -+ u8 val; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* clear the array just in case */ -+ memset(last_sent, 0, ARRAY_SIZE(last_sent)); -+ -+ /* n comes in bytes; convert to ints */ -+ n /= sizeof(int); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* let everybody know we're now transmitting */ -+ dev->transmitting = true; -+ -+ /* and set the carrier values for transmission */ -+ ite_set_carrier_params(dev); -+ -+ /* calculate how much time we can send in one byte */ -+ max_rle_us = -+ (ITE_BAUDRATE_DIVISOR * dev->params.sample_period * -+ ITE_TX_MAX_RLE) / 1000; -+ -+ /* disable the receiver */ -+ dev->params.disable_rx(dev); -+ -+ /* this is where we'll begin filling in the FIFO, until it's full. -+ * then we'll just activate the interrupt, wait for it to wake us up -+ * again, disable it, continue filling the FIFO... until everything -+ * has been pushed out */ -+ fifo_avail = -+ ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); -+ -+ while (n > 0 && dev->in_use) { -+ /* transmit the next sample */ -+ is_pulse = !is_pulse; -+ remaining_us = *(txbuf++); -+ n--; -+ -+ ite_dbg("%s: %ld", -+ ((is_pulse) ? "pulse" : "space"), -+ (long int) -+ remaining_us); -+ -+ /* repeat while the pulse is non-zero length */ -+ while (remaining_us > 0 && dev->in_use) { -+ if (remaining_us > max_rle_us) -+ next_rle_us = max_rle_us; -+ -+ else -+ next_rle_us = remaining_us; -+ -+ remaining_us -= next_rle_us; -+ -+ /* check what's the length we have to pump out */ -+ val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us; -+ -+ /* put it into the sent buffer */ -+ last_sent[last_idx++] = val; -+ last_idx &= (ITE_TX_FIFO_LEN); -+ -+ /* encode it for 7 bits */ -+ val = (val - 1) & ITE_TX_RLE_MASK; -+ -+ /* take into account pulse/space prefix */ -+ if (is_pulse) -+ val |= ITE_TX_PULSE; -+ -+ else -+ val |= ITE_TX_SPACE; -+ -+ /* -+ * if we get to 0 available, read again, just in case -+ * some other slot got freed -+ */ -+ if (fifo_avail <= 0) -+ fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev); -+ -+ /* if it's still full */ -+ if (fifo_avail <= 0) { -+ /* enable the tx interrupt */ -+ dev->params. -+ enable_tx_interrupt(dev); -+ -+ /* drop the spinlock */ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ /* wait for the FIFO to empty enough */ -+ wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8); -+ -+ /* get the spinlock again */ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* disable the tx interrupt again. */ -+ dev->params. -+ disable_tx_interrupt(dev); -+ } -+ -+ /* now send the byte through the FIFO */ -+ dev->params.put_tx_byte(dev, val); -+ fifo_avail--; -+ } -+ } -+ -+ /* wait and don't return until the whole FIFO has been sent out; -+ * otherwise we could configure the RX carrier params instead of the -+ * TX ones while the transmission is still being performed! */ -+ fifo_remaining = dev->params.get_tx_used_slots(dev); -+ remaining_us = 0; -+ while (fifo_remaining > 0) { -+ fifo_remaining--; -+ last_idx--; -+ last_idx &= (ITE_TX_FIFO_LEN - 1); -+ remaining_us += last_sent[last_idx]; -+ } -+ remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE); -+ -+ /* drop the spinlock while we sleep */ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ /* sleep remaining_us microseconds */ -+ mdelay(DIV_ROUND_UP(remaining_us, 1000)); -+ -+ /* reacquire the spinlock */ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* now we're not transmitting anymore */ -+ dev->transmitting = false; -+ -+ /* and set the carrier values for reception */ -+ ite_set_carrier_params(dev); -+ -+ /* reenable the receiver */ -+ if (dev->in_use) -+ dev->params.enable_rx(dev); -+ -+ /* notify transmission end */ -+ wake_up_interruptible(&dev->tx_ended); -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return ret; -+} -+ -+/* idle the receiver if needed */ -+static void ite_s_idle(struct rc_dev *rcdev, bool enable) -+{ -+ unsigned long flags; -+ struct ite_dev *dev = rcdev->priv; -+ -+ ite_dbg("%s called", __func__); -+ -+ if (enable) { -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->params.idle_rx(dev); -+ spin_unlock_irqrestore(&dev->lock, flags); -+ } -+} -+ -+ -+/* IT8712F HW-specific functions */ -+ -+/* retrieve a bitmask of the current causes for a pending interrupt; this may -+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN -+ * */ -+static int it87_get_irq_causes(struct ite_dev *dev) -+{ -+ u8 iflags; -+ int ret = 0; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* read the interrupt flags */ -+ iflags = inb(dev->cir_addr + IT87_IIR) & IT87_II; -+ -+ switch (iflags) { -+ case IT87_II_RXDS: -+ ret = ITE_IRQ_RX_FIFO; -+ break; -+ case IT87_II_RXFO: -+ ret = ITE_IRQ_RX_FIFO_OVERRUN; -+ break; -+ case IT87_II_TXLDL: -+ ret = ITE_IRQ_TX_FIFO; -+ break; -+ } -+ -+ return ret; -+} -+ -+/* set the carrier parameters; to be called with the spinlock held */ -+static void it87_set_carrier_params(struct ite_dev *dev, bool high_freq, -+ bool use_demodulator, -+ u8 carrier_freq_bits, u8 allowance_bits, -+ u8 pulse_width_bits) -+{ -+ u8 val; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* program the RCR register */ -+ val = inb(dev->cir_addr + IT87_RCR) -+ & ~(IT87_HCFS | IT87_RXEND | IT87_RXDCR); -+ -+ if (high_freq) -+ val |= IT87_HCFS; -+ -+ if (use_demodulator) -+ val |= IT87_RXEND; -+ -+ val |= allowance_bits; -+ -+ outb(val, dev->cir_addr + IT87_RCR); -+ -+ /* program the TCR2 register */ -+ outb((carrier_freq_bits << IT87_CFQ_SHIFT) | pulse_width_bits, -+ dev->cir_addr + IT87_TCR2); -+} -+ -+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock -+ * held */ -+static int it87_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size) -+{ -+ int fifo, read = 0; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* read how many bytes are still in the FIFO */ -+ fifo = inb(dev->cir_addr + IT87_RSR) & IT87_RXFBC; -+ -+ while (fifo > 0 && buf_size > 0) { -+ *(buf++) = inb(dev->cir_addr + IT87_DR); -+ fifo--; -+ read++; -+ buf_size--; -+ } -+ -+ return read; -+} -+ -+/* return how many bytes are still in the FIFO; this will be called -+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get -+ * empty; let's expect this won't be a problem */ -+static int it87_get_tx_used_slots(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ return inb(dev->cir_addr + IT87_TSR) & IT87_TXFBC; -+} -+ -+/* put a byte to the TX fifo; this should be called with the spinlock held */ -+static void it87_put_tx_byte(struct ite_dev *dev, u8 value) -+{ -+ outb(value, dev->cir_addr + IT87_DR); -+} -+ -+/* idle the receiver so that we won't receive samples until another -+ pulse is detected; this must be called with the device spinlock held */ -+static void it87_idle_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable streaming by clearing RXACT writing it as 1 */ -+ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXACT, -+ dev->cir_addr + IT87_RCR); -+ -+ /* clear the FIFO */ -+ outb(inb(dev->cir_addr + IT87_TCR1) | IT87_FIFOCLR, -+ dev->cir_addr + IT87_TCR1); -+} -+ -+/* disable the receiver; this must be called with the device spinlock held */ -+static void it87_disable_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable the receiver interrupts */ -+ outb(inb(dev->cir_addr + IT87_IER) & ~(IT87_RDAIE | IT87_RFOIE), -+ dev->cir_addr + IT87_IER); -+ -+ /* disable the receiver */ -+ outb(inb(dev->cir_addr + IT87_RCR) & ~IT87_RXEN, -+ dev->cir_addr + IT87_RCR); -+ -+ /* clear the FIFO and RXACT (actually RXACT should have been cleared -+ * in the previous outb() call) */ -+ it87_idle_rx(dev); -+} -+ -+/* enable the receiver; this must be called with the device spinlock held */ -+static void it87_enable_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* enable the receiver by setting RXEN */ -+ outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXEN, -+ dev->cir_addr + IT87_RCR); -+ -+ /* just prepare it to idle for the next reception */ -+ it87_idle_rx(dev); -+ -+ /* enable the receiver interrupts and master enable flag */ -+ outb(inb(dev->cir_addr + IT87_IER) | IT87_RDAIE | IT87_RFOIE | IT87_IEC, -+ dev->cir_addr + IT87_IER); -+} -+ -+/* disable the transmitter interrupt; this must be called with the device -+ * spinlock held */ -+static void it87_disable_tx_interrupt(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable the transmitter interrupts */ -+ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_TLDLIE, -+ dev->cir_addr + IT87_IER); -+} -+ -+/* enable the transmitter interrupt; this must be called with the device -+ * spinlock held */ -+static void it87_enable_tx_interrupt(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* enable the transmitter interrupts and master enable flag */ -+ outb(inb(dev->cir_addr + IT87_IER) | IT87_TLDLIE | IT87_IEC, -+ dev->cir_addr + IT87_IER); -+} -+ -+/* disable the device; this must be called with the device spinlock held */ -+static void it87_disable(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* clear out all interrupt enable flags */ -+ outb(inb(dev->cir_addr + IT87_IER) & -+ ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE), -+ dev->cir_addr + IT87_IER); -+ -+ /* disable the receiver */ -+ it87_disable_rx(dev); -+ -+ /* erase the FIFO */ -+ outb(IT87_FIFOCLR | inb(dev->cir_addr + IT87_TCR1), -+ dev->cir_addr + IT87_TCR1); -+} -+ -+/* initialize the hardware */ -+static void it87_init_hardware(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* enable just the baud rate divisor register, -+ disabling all the interrupts at the same time */ -+ outb((inb(dev->cir_addr + IT87_IER) & -+ ~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE)) | IT87_BR, -+ dev->cir_addr + IT87_IER); -+ -+ /* write out the baud rate divisor */ -+ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR); -+ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR); -+ -+ /* disable the baud rate divisor register again */ -+ outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR, -+ dev->cir_addr + IT87_IER); -+ -+ /* program the RCR register defaults */ -+ outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR); -+ -+ /* program the TCR1 register */ -+ outb(IT87_TXMPM_DEFAULT | IT87_TXENDF | IT87_TXRLE -+ | IT87_FIFOTL_DEFAULT | IT87_FIFOCLR, -+ dev->cir_addr + IT87_TCR1); -+ -+ /* program the carrier parameters */ -+ ite_set_carrier_params(dev); -+} -+ -+/* IT8512F on ITE8708 HW-specific functions */ -+ -+/* retrieve a bitmask of the current causes for a pending interrupt; this may -+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN -+ * */ -+static int it8708_get_irq_causes(struct ite_dev *dev) -+{ -+ u8 iflags; -+ int ret = 0; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* read the interrupt flags */ -+ iflags = inb(dev->cir_addr + IT8708_C0IIR); -+ -+ if (iflags & IT85_TLDLI) -+ ret |= ITE_IRQ_TX_FIFO; -+ if (iflags & IT85_RDAI) -+ ret |= ITE_IRQ_RX_FIFO; -+ if (iflags & IT85_RFOI) -+ ret |= ITE_IRQ_RX_FIFO_OVERRUN; -+ -+ return ret; -+} -+ -+/* set the carrier parameters; to be called with the spinlock held */ -+static void it8708_set_carrier_params(struct ite_dev *dev, bool high_freq, -+ bool use_demodulator, -+ u8 carrier_freq_bits, u8 allowance_bits, -+ u8 pulse_width_bits) -+{ -+ u8 val; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* program the C0CFR register, with HRAE=1 */ -+ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE, -+ dev->cir_addr + IT8708_BANKSEL); -+ -+ val = (inb(dev->cir_addr + IT8708_C0CFR) -+ & ~(IT85_HCFS | IT85_CFQ)) | carrier_freq_bits; -+ -+ if (high_freq) -+ val |= IT85_HCFS; -+ -+ outb(val, dev->cir_addr + IT8708_C0CFR); -+ -+ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE, -+ dev->cir_addr + IT8708_BANKSEL); -+ -+ /* program the C0RCR register */ -+ val = inb(dev->cir_addr + IT8708_C0RCR) -+ & ~(IT85_RXEND | IT85_RXDCR); -+ -+ if (use_demodulator) -+ val |= IT85_RXEND; -+ -+ val |= allowance_bits; -+ -+ outb(val, dev->cir_addr + IT8708_C0RCR); -+ -+ /* program the C0TCR register */ -+ val = inb(dev->cir_addr + IT8708_C0TCR) & ~IT85_TXMPW; -+ val |= pulse_width_bits; -+ outb(val, dev->cir_addr + IT8708_C0TCR); -+} -+ -+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock -+ * held */ -+static int it8708_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size) -+{ -+ int fifo, read = 0; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* read how many bytes are still in the FIFO */ -+ fifo = inb(dev->cir_addr + IT8708_C0RFSR) & IT85_RXFBC; -+ -+ while (fifo > 0 && buf_size > 0) { -+ *(buf++) = inb(dev->cir_addr + IT8708_C0DR); -+ fifo--; -+ read++; -+ buf_size--; -+ } -+ -+ return read; -+} -+ -+/* return how many bytes are still in the FIFO; this will be called -+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get -+ * empty; let's expect this won't be a problem */ -+static int it8708_get_tx_used_slots(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ return inb(dev->cir_addr + IT8708_C0TFSR) & IT85_TXFBC; -+} -+ -+/* put a byte to the TX fifo; this should be called with the spinlock held */ -+static void it8708_put_tx_byte(struct ite_dev *dev, u8 value) -+{ -+ outb(value, dev->cir_addr + IT8708_C0DR); -+} -+ -+/* idle the receiver so that we won't receive samples until another -+ pulse is detected; this must be called with the device spinlock held */ -+static void it8708_idle_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable streaming by clearing RXACT writing it as 1 */ -+ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXACT, -+ dev->cir_addr + IT8708_C0RCR); -+ -+ /* clear the FIFO */ -+ outb(inb(dev->cir_addr + IT8708_C0MSTCR) | IT85_FIFOCLR, -+ dev->cir_addr + IT8708_C0MSTCR); -+} -+ -+/* disable the receiver; this must be called with the device spinlock held */ -+static void it8708_disable_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable the receiver interrupts */ -+ outb(inb(dev->cir_addr + IT8708_C0IER) & -+ ~(IT85_RDAIE | IT85_RFOIE), -+ dev->cir_addr + IT8708_C0IER); -+ -+ /* disable the receiver */ -+ outb(inb(dev->cir_addr + IT8708_C0RCR) & ~IT85_RXEN, -+ dev->cir_addr + IT8708_C0RCR); -+ -+ /* clear the FIFO and RXACT (actually RXACT should have been cleared -+ * in the previous outb() call) */ -+ it8708_idle_rx(dev); -+} -+ -+/* enable the receiver; this must be called with the device spinlock held */ -+static void it8708_enable_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* enable the receiver by setting RXEN */ -+ outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXEN, -+ dev->cir_addr + IT8708_C0RCR); -+ -+ /* just prepare it to idle for the next reception */ -+ it8708_idle_rx(dev); -+ -+ /* enable the receiver interrupts and master enable flag */ -+ outb(inb(dev->cir_addr + IT8708_C0IER) -+ |IT85_RDAIE | IT85_RFOIE | IT85_IEC, -+ dev->cir_addr + IT8708_C0IER); -+} -+ -+/* disable the transmitter interrupt; this must be called with the device -+ * spinlock held */ -+static void it8708_disable_tx_interrupt(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable the transmitter interrupts */ -+ outb(inb(dev->cir_addr + IT8708_C0IER) & ~IT85_TLDLIE, -+ dev->cir_addr + IT8708_C0IER); -+} -+ -+/* enable the transmitter interrupt; this must be called with the device -+ * spinlock held */ -+static void it8708_enable_tx_interrupt(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* enable the transmitter interrupts and master enable flag */ -+ outb(inb(dev->cir_addr + IT8708_C0IER) -+ |IT85_TLDLIE | IT85_IEC, -+ dev->cir_addr + IT8708_C0IER); -+} -+ -+/* disable the device; this must be called with the device spinlock held */ -+static void it8708_disable(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* clear out all interrupt enable flags */ -+ outb(inb(dev->cir_addr + IT8708_C0IER) & -+ ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), -+ dev->cir_addr + IT8708_C0IER); -+ -+ /* disable the receiver */ -+ it8708_disable_rx(dev); -+ -+ /* erase the FIFO */ -+ outb(IT85_FIFOCLR | inb(dev->cir_addr + IT8708_C0MSTCR), -+ dev->cir_addr + IT8708_C0MSTCR); -+} -+ -+/* initialize the hardware */ -+static void it8708_init_hardware(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable all the interrupts */ -+ outb(inb(dev->cir_addr + IT8708_C0IER) & -+ ~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE), -+ dev->cir_addr + IT8708_C0IER); -+ -+ /* program the baud rate divisor */ -+ outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE, -+ dev->cir_addr + IT8708_BANKSEL); -+ -+ outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT8708_C0BDLR); -+ outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, -+ dev->cir_addr + IT8708_C0BDHR); -+ -+ outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE, -+ dev->cir_addr + IT8708_BANKSEL); -+ -+ /* program the C0MSTCR register defaults */ -+ outb((inb(dev->cir_addr + IT8708_C0MSTCR) & -+ ~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL | -+ IT85_FIFOCLR | IT85_RESET)) | -+ IT85_FIFOTL_DEFAULT, -+ dev->cir_addr + IT8708_C0MSTCR); -+ -+ /* program the C0RCR register defaults */ -+ outb((inb(dev->cir_addr + IT8708_C0RCR) & -+ ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND | -+ IT85_RXACT | IT85_RXDCR)) | -+ ITE_RXDCR_DEFAULT, -+ dev->cir_addr + IT8708_C0RCR); -+ -+ /* program the C0TCR register defaults */ -+ outb((inb(dev->cir_addr + IT8708_C0TCR) & -+ ~(IT85_TXMPM | IT85_TXMPW)) -+ |IT85_TXRLE | IT85_TXENDF | -+ IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT, -+ dev->cir_addr + IT8708_C0TCR); -+ -+ /* program the carrier parameters */ -+ ite_set_carrier_params(dev); -+} -+ -+/* IT8512F on ITE8709 HW-specific functions */ -+ -+/* read a byte from the SRAM module */ -+static inline u8 it8709_rm(struct ite_dev *dev, int index) -+{ -+ outb(index, dev->cir_addr + IT8709_RAM_IDX); -+ return inb(dev->cir_addr + IT8709_RAM_VAL); -+} -+ -+/* write a byte to the SRAM module */ -+static inline void it8709_wm(struct ite_dev *dev, u8 val, int index) -+{ -+ outb(index, dev->cir_addr + IT8709_RAM_IDX); -+ outb(val, dev->cir_addr + IT8709_RAM_VAL); -+} -+ -+static void it8709_wait(struct ite_dev *dev) -+{ -+ int i = 0; -+ /* -+ * loop until device tells it's ready to continue -+ * iterations count is usually ~750 but can sometimes achieve 13000 -+ */ -+ for (i = 0; i < 15000; i++) { -+ udelay(2); -+ if (it8709_rm(dev, IT8709_MODE) == IT8709_IDLE) -+ break; -+ } -+} -+ -+/* read the value of a CIR register */ -+static u8 it8709_rr(struct ite_dev *dev, int index) -+{ -+ /* just wait in case the previous access was a write */ -+ it8709_wait(dev); -+ it8709_wm(dev, index, IT8709_REG_IDX); -+ it8709_wm(dev, IT8709_READ, IT8709_MODE); -+ -+ /* wait for the read data to be available */ -+ it8709_wait(dev); -+ -+ /* return the read value */ -+ return it8709_rm(dev, IT8709_REG_VAL); -+} -+ -+/* write the value of a CIR register */ -+static void it8709_wr(struct ite_dev *dev, u8 val, int index) -+{ -+ /* we wait before writing, and not afterwards, since this allows us to -+ * pipeline the host CPU with the microcontroller */ -+ it8709_wait(dev); -+ it8709_wm(dev, val, IT8709_REG_VAL); -+ it8709_wm(dev, index, IT8709_REG_IDX); -+ it8709_wm(dev, IT8709_WRITE, IT8709_MODE); -+} -+ -+/* retrieve a bitmask of the current causes for a pending interrupt; this may -+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN -+ * */ -+static int it8709_get_irq_causes(struct ite_dev *dev) -+{ -+ u8 iflags; -+ int ret = 0; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* read the interrupt flags */ -+ iflags = it8709_rm(dev, IT8709_IIR); -+ -+ if (iflags & IT85_TLDLI) -+ ret |= ITE_IRQ_TX_FIFO; -+ if (iflags & IT85_RDAI) -+ ret |= ITE_IRQ_RX_FIFO; -+ if (iflags & IT85_RFOI) -+ ret |= ITE_IRQ_RX_FIFO_OVERRUN; -+ -+ return ret; -+} -+ -+/* set the carrier parameters; to be called with the spinlock held */ -+static void it8709_set_carrier_params(struct ite_dev *dev, bool high_freq, -+ bool use_demodulator, -+ u8 carrier_freq_bits, u8 allowance_bits, -+ u8 pulse_width_bits) -+{ -+ u8 val; -+ -+ ite_dbg("%s called", __func__); -+ -+ val = (it8709_rr(dev, IT85_C0CFR) -+ &~(IT85_HCFS | IT85_CFQ)) | -+ carrier_freq_bits; -+ -+ if (high_freq) -+ val |= IT85_HCFS; -+ -+ it8709_wr(dev, val, IT85_C0CFR); -+ -+ /* program the C0RCR register */ -+ val = it8709_rr(dev, IT85_C0RCR) -+ & ~(IT85_RXEND | IT85_RXDCR); -+ -+ if (use_demodulator) -+ val |= IT85_RXEND; -+ -+ val |= allowance_bits; -+ -+ it8709_wr(dev, val, IT85_C0RCR); -+ -+ /* program the C0TCR register */ -+ val = it8709_rr(dev, IT85_C0TCR) & ~IT85_TXMPW; -+ val |= pulse_width_bits; -+ it8709_wr(dev, val, IT85_C0TCR); -+} -+ -+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock -+ * held */ -+static int it8709_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size) -+{ -+ int fifo, read = 0; -+ -+ ite_dbg("%s called", __func__); -+ -+ /* read how many bytes are still in the FIFO */ -+ fifo = it8709_rm(dev, IT8709_RFSR) & IT85_RXFBC; -+ -+ while (fifo > 0 && buf_size > 0) { -+ *(buf++) = it8709_rm(dev, IT8709_FIFO + read); -+ fifo--; -+ read++; -+ buf_size--; -+ } -+ -+ /* 'clear' the FIFO by setting the writing index to 0; this is -+ * completely bound to be racy, but we can't help it, since it's a -+ * limitation of the protocol */ -+ it8709_wm(dev, 0, IT8709_RFSR); -+ -+ return read; -+} -+ -+/* return how many bytes are still in the FIFO; this will be called -+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get -+ * empty; let's expect this won't be a problem */ -+static int it8709_get_tx_used_slots(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ return it8709_rr(dev, IT85_C0TFSR) & IT85_TXFBC; -+} -+ -+/* put a byte to the TX fifo; this should be called with the spinlock held */ -+static void it8709_put_tx_byte(struct ite_dev *dev, u8 value) -+{ -+ it8709_wr(dev, value, IT85_C0DR); -+} -+ -+/* idle the receiver so that we won't receive samples until another -+ pulse is detected; this must be called with the device spinlock held */ -+static void it8709_idle_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable streaming by clearing RXACT writing it as 1 */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXACT, -+ IT85_C0RCR); -+ -+ /* clear the FIFO */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0MSTCR) | IT85_FIFOCLR, -+ IT85_C0MSTCR); -+} -+ -+/* disable the receiver; this must be called with the device spinlock held */ -+static void it8709_disable_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable the receiver interrupts */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & -+ ~(IT85_RDAIE | IT85_RFOIE), -+ IT85_C0IER); -+ -+ /* disable the receiver */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) & ~IT85_RXEN, -+ IT85_C0RCR); -+ -+ /* clear the FIFO and RXACT (actually RXACT should have been cleared -+ * in the previous it8709_wr(dev, ) call) */ -+ it8709_idle_rx(dev); -+} -+ -+/* enable the receiver; this must be called with the device spinlock held */ -+static void it8709_enable_rx(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* enable the receiver by setting RXEN */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXEN, -+ IT85_C0RCR); -+ -+ /* just prepare it to idle for the next reception */ -+ it8709_idle_rx(dev); -+ -+ /* enable the receiver interrupts and master enable flag */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) -+ |IT85_RDAIE | IT85_RFOIE | IT85_IEC, -+ IT85_C0IER); -+} -+ -+/* disable the transmitter interrupt; this must be called with the device -+ * spinlock held */ -+static void it8709_disable_tx_interrupt(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable the transmitter interrupts */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ~IT85_TLDLIE, -+ IT85_C0IER); -+} -+ -+/* enable the transmitter interrupt; this must be called with the device -+ * spinlock held */ -+static void it8709_enable_tx_interrupt(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* enable the transmitter interrupts and master enable flag */ -+ it8709_wr(dev, it8709_rr(dev, IT85_C0IER) -+ |IT85_TLDLIE | IT85_IEC, -+ IT85_C0IER); -+} -+ -+/* disable the device; this must be called with the device spinlock held */ -+static void it8709_disable(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* clear out all interrupt enable flags */ -+ it8709_wr(dev, -+ it8709_rr(dev, -+ IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | -+ IT85_RDAIE | -+ IT85_TLDLIE), IT85_C0IER); -+ -+ /* disable the receiver */ -+ it8709_disable_rx(dev); -+ -+ /* erase the FIFO */ -+ it8709_wr(dev, IT85_FIFOCLR | it8709_rr(dev, IT85_C0MSTCR), -+ IT85_C0MSTCR); -+} -+ -+/* initialize the hardware */ -+static void it8709_init_hardware(struct ite_dev *dev) -+{ -+ ite_dbg("%s called", __func__); -+ -+ /* disable all the interrupts */ -+ it8709_wr(dev, -+ it8709_rr(dev, -+ IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE | -+ IT85_RDAIE | -+ IT85_TLDLIE), IT85_C0IER); -+ -+ /* program the baud rate divisor */ -+ it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR); -+ it8709_wr(dev, (ITE_BAUDRATE_DIVISOR >> 8) & 0xff, -+ IT85_C0BDHR); -+ -+ /* program the C0MSTCR register defaults */ -+ it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL | -+ IT85_ILE -+ | IT85_FIFOTL -+ | -+ IT85_FIFOCLR -+ | -+ IT85_RESET)) -+ | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR); -+ -+ /* program the C0RCR register defaults */ -+ it8709_wr(dev, -+ (it8709_rr(dev, IT85_C0RCR) & -+ ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND -+ | IT85_RXACT | IT85_RXDCR)) | -+ ITE_RXDCR_DEFAULT, IT85_C0RCR); -+ -+ /* program the C0TCR register defaults */ -+ it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR) -+ &~(IT85_TXMPM | IT85_TXMPW)) -+ |IT85_TXRLE | IT85_TXENDF | -+ IT85_TXMPM_DEFAULT | -+ IT85_TXMPW_DEFAULT, IT85_C0TCR); -+ -+ /* program the carrier parameters */ -+ ite_set_carrier_params(dev); -+} -+ -+ -+/* generic hardware setup/teardown code */ -+ -+/* activate the device for use */ -+static int ite_open(struct rc_dev *rcdev) -+{ -+ struct ite_dev *dev = rcdev->priv; -+ unsigned long flags; -+ -+ ite_dbg("%s called", __func__); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->in_use = true; -+ -+ /* enable the receiver */ -+ dev->params.enable_rx(dev); -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return 0; -+} -+ -+/* deactivate the device for use */ -+static void ite_close(struct rc_dev *rcdev) -+{ -+ struct ite_dev *dev = rcdev->priv; -+ unsigned long flags; -+ -+ ite_dbg("%s called", __func__); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ dev->in_use = false; -+ -+ /* wait for any transmission to end */ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ wait_event_interruptible(dev->tx_ended, !dev->transmitting); -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ dev->params.disable(dev); -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+} -+ -+/* supported models and their parameters */ -+static const struct ite_dev_params ite_dev_descs[] = { -+ { /* 0: ITE8704 */ -+ .model = "ITE8704 CIR transceiver", -+ .io_region_size = IT87_IOREG_LENGTH, -+ .hw_tx_capable = true, -+ .sample_period = (u32) (1000000000ULL / 115200), -+ .tx_carrier_freq = 38000, -+ .tx_duty_cycle = 33, -+ .rx_low_carrier_freq = 0, -+ .rx_high_carrier_freq = 0, -+ -+ /* operations */ -+ .get_irq_causes = it87_get_irq_causes, -+ .enable_rx = it87_enable_rx, -+ .idle_rx = it87_idle_rx, -+ .disable_rx = it87_idle_rx, -+ .get_rx_bytes = it87_get_rx_bytes, -+ .enable_tx_interrupt = it87_enable_tx_interrupt, -+ .disable_tx_interrupt = it87_disable_tx_interrupt, -+ .get_tx_used_slots = it87_get_tx_used_slots, -+ .put_tx_byte = it87_put_tx_byte, -+ .disable = it87_disable, -+ .init_hardware = it87_init_hardware, -+ .set_carrier_params = it87_set_carrier_params, -+ }, -+ { /* 1: ITE8713 */ -+ .model = "ITE8713 CIR transceiver", -+ .io_region_size = IT87_IOREG_LENGTH, -+ .hw_tx_capable = true, -+ .sample_period = (u32) (1000000000ULL / 115200), -+ .tx_carrier_freq = 38000, -+ .tx_duty_cycle = 33, -+ .rx_low_carrier_freq = 0, -+ .rx_high_carrier_freq = 0, -+ -+ /* operations */ -+ .get_irq_causes = it87_get_irq_causes, -+ .enable_rx = it87_enable_rx, -+ .idle_rx = it87_idle_rx, -+ .disable_rx = it87_idle_rx, -+ .get_rx_bytes = it87_get_rx_bytes, -+ .enable_tx_interrupt = it87_enable_tx_interrupt, -+ .disable_tx_interrupt = it87_disable_tx_interrupt, -+ .get_tx_used_slots = it87_get_tx_used_slots, -+ .put_tx_byte = it87_put_tx_byte, -+ .disable = it87_disable, -+ .init_hardware = it87_init_hardware, -+ .set_carrier_params = it87_set_carrier_params, -+ }, -+ { /* 2: ITE8708 */ -+ .model = "ITE8708 CIR transceiver", -+ .io_region_size = IT8708_IOREG_LENGTH, -+ .hw_tx_capable = true, -+ .sample_period = (u32) (1000000000ULL / 115200), -+ .tx_carrier_freq = 38000, -+ .tx_duty_cycle = 33, -+ .rx_low_carrier_freq = 0, -+ .rx_high_carrier_freq = 0, -+ -+ /* operations */ -+ .get_irq_causes = it8708_get_irq_causes, -+ .enable_rx = it8708_enable_rx, -+ .idle_rx = it8708_idle_rx, -+ .disable_rx = it8708_idle_rx, -+ .get_rx_bytes = it8708_get_rx_bytes, -+ .enable_tx_interrupt = it8708_enable_tx_interrupt, -+ .disable_tx_interrupt = -+ it8708_disable_tx_interrupt, -+ .get_tx_used_slots = it8708_get_tx_used_slots, -+ .put_tx_byte = it8708_put_tx_byte, -+ .disable = it8708_disable, -+ .init_hardware = it8708_init_hardware, -+ .set_carrier_params = it8708_set_carrier_params, -+ }, -+ { /* 3: ITE8709 */ -+ .model = "ITE8709 CIR transceiver", -+ .io_region_size = IT8709_IOREG_LENGTH, -+ .hw_tx_capable = true, -+ .sample_period = (u32) (1000000000ULL / 115200), -+ .tx_carrier_freq = 38000, -+ .tx_duty_cycle = 33, -+ .rx_low_carrier_freq = 0, -+ .rx_high_carrier_freq = 0, -+ -+ /* operations */ -+ .get_irq_causes = it8709_get_irq_causes, -+ .enable_rx = it8709_enable_rx, -+ .idle_rx = it8709_idle_rx, -+ .disable_rx = it8709_idle_rx, -+ .get_rx_bytes = it8709_get_rx_bytes, -+ .enable_tx_interrupt = it8709_enable_tx_interrupt, -+ .disable_tx_interrupt = -+ it8709_disable_tx_interrupt, -+ .get_tx_used_slots = it8709_get_tx_used_slots, -+ .put_tx_byte = it8709_put_tx_byte, -+ .disable = it8709_disable, -+ .init_hardware = it8709_init_hardware, -+ .set_carrier_params = it8709_set_carrier_params, -+ }, -+}; -+ -+static const struct pnp_device_id ite_ids[] = { -+ {"ITE8704", 0}, /* Default model */ -+ {"ITE8713", 1}, /* CIR found in EEEBox 1501U */ -+ {"ITE8708", 2}, /* Bridged IT8512 */ -+ {"ITE8709", 3}, /* SRAM-Bridged IT8512 */ -+ {"", 0}, -+}; -+ -+/* allocate memory, probe hardware, and initialize everything */ -+static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id -+ *dev_id) -+{ -+ const struct ite_dev_params *dev_desc = NULL; -+ struct ite_dev *itdev = NULL; -+ struct rc_dev *rdev = NULL; -+ int ret = -ENOMEM; -+ int model_no; -+ -+ ite_dbg("%s called", __func__); -+ -+ itdev = kzalloc(sizeof(struct ite_dev), GFP_KERNEL); -+ if (!itdev) -+ return ret; -+ -+ /* input device for IR remote (and tx) */ -+ rdev = rc_allocate_device(); -+ if (!rdev) -+ goto failure; -+ -+ ret = -ENODEV; -+ -+ /* get the model number */ -+ model_no = (int)dev_id->driver_data; -+ ite_pr(KERN_NOTICE, "Auto-detected model: %s\n", -+ ite_dev_descs[model_no].model); -+ -+ if (model_number >= 0 && model_number < ARRAY_SIZE(ite_dev_descs)) { -+ model_no = model_number; -+ ite_pr(KERN_NOTICE, "The model has been fixed by a module " -+ "parameter."); -+ } -+ -+ ite_pr(KERN_NOTICE, "Using model: %s\n", ite_dev_descs[model_no].model); -+ -+ /* get the description for the device */ -+ dev_desc = &ite_dev_descs[model_no]; -+ -+ /* validate pnp resources */ -+ if (!pnp_port_valid(pdev, 0) || -+ pnp_port_len(pdev, 0) != dev_desc->io_region_size) { -+ dev_err(&pdev->dev, "IR PNP Port not valid!\n"); -+ goto failure; -+ } -+ -+ if (!pnp_irq_valid(pdev, 0)) { -+ dev_err(&pdev->dev, "PNP IRQ not valid!\n"); -+ goto failure; -+ } -+ -+ /* store resource values */ -+ itdev->cir_addr = pnp_port_start(pdev, 0); -+ itdev->cir_irq = pnp_irq(pdev, 0); -+ -+ /* initialize spinlocks */ -+ spin_lock_init(&itdev->lock); -+ -+ /* initialize raw event */ -+ init_ir_raw_event(&itdev->rawir); -+ -+ ret = -EBUSY; -+ /* now claim resources */ -+ if (!request_region(itdev->cir_addr, -+ dev_desc->io_region_size, ITE_DRIVER_NAME)) -+ goto failure; -+ -+ if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED, -+ ITE_DRIVER_NAME, (void *)itdev)) -+ goto failure; -+ -+ /* set driver data into the pnp device */ -+ pnp_set_drvdata(pdev, itdev); -+ itdev->pdev = pdev; -+ -+ /* initialize waitqueues for transmission */ -+ init_waitqueue_head(&itdev->tx_queue); -+ init_waitqueue_head(&itdev->tx_ended); -+ -+ /* copy model-specific parameters */ -+ itdev->params = *dev_desc; -+ -+ /* apply any overrides */ -+ if (sample_period > 0) -+ itdev->params.sample_period = sample_period; -+ -+ if (tx_carrier_freq > 0) -+ itdev->params.tx_carrier_freq = tx_carrier_freq; -+ -+ if (tx_duty_cycle > 0 && tx_duty_cycle <= 100) -+ itdev->params.tx_duty_cycle = tx_duty_cycle; -+ -+ if (rx_low_carrier_freq > 0) -+ itdev->params.rx_low_carrier_freq = rx_low_carrier_freq; -+ -+ if (rx_high_carrier_freq > 0) -+ itdev->params.rx_high_carrier_freq = rx_high_carrier_freq; -+ -+ /* print out parameters */ -+ ite_pr(KERN_NOTICE, "TX-capable: %d\n", (int) -+ itdev->params.hw_tx_capable); -+ ite_pr(KERN_NOTICE, "Sample period (ns): %ld\n", (long) -+ itdev->params.sample_period); -+ ite_pr(KERN_NOTICE, "TX carrier frequency (Hz): %d\n", (int) -+ itdev->params.tx_carrier_freq); -+ ite_pr(KERN_NOTICE, "TX duty cycle (%%): %d\n", (int) -+ itdev->params.tx_duty_cycle); -+ ite_pr(KERN_NOTICE, "RX low carrier frequency (Hz): %d\n", (int) -+ itdev->params.rx_low_carrier_freq); -+ ite_pr(KERN_NOTICE, "RX high carrier frequency (Hz): %d\n", (int) -+ itdev->params.rx_high_carrier_freq); -+ -+ /* set up hardware initial state */ -+ itdev->params.init_hardware(itdev); -+ -+ /* set up ir-core props */ -+ rdev->priv = itdev; -+ rdev->driver_type = RC_DRIVER_IR_RAW; -+ rdev->allowed_protos = RC_TYPE_ALL; -+ rdev->open = ite_open; -+ rdev->close = ite_close; -+ rdev->s_idle = ite_s_idle; -+ rdev->s_rx_carrier_range = ite_set_rx_carrier_range; -+ rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT; -+ rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT; -+ rdev->timeout = ITE_IDLE_TIMEOUT; -+ rdev->rx_resolution = ITE_BAUDRATE_DIVISOR * -+ itdev->params.sample_period; -+ rdev->tx_resolution = ITE_BAUDRATE_DIVISOR * -+ itdev->params.sample_period; -+ -+ /* set up transmitter related values if needed */ -+ if (itdev->params.hw_tx_capable) { -+ rdev->tx_ir = ite_tx_ir; -+ rdev->s_tx_carrier = ite_set_tx_carrier; -+ rdev->s_tx_duty_cycle = ite_set_tx_duty_cycle; -+ } -+ -+ rdev->input_name = dev_desc->model; -+ rdev->input_id.bustype = BUS_HOST; -+ rdev->input_id.vendor = PCI_VENDOR_ID_ITE; -+ rdev->input_id.product = 0; -+ rdev->input_id.version = 0; -+ rdev->driver_name = ITE_DRIVER_NAME; -+ rdev->map_name = RC_MAP_RC6_MCE; -+ -+ ret = rc_register_device(rdev); -+ if (ret) -+ goto failure; -+ -+ itdev->rdev = rdev; -+ ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); -+ -+ return 0; -+ -+failure: -+ if (itdev->cir_irq) -+ free_irq(itdev->cir_irq, itdev); -+ -+ if (itdev->cir_addr) -+ release_region(itdev->cir_addr, itdev->params.io_region_size); -+ -+ rc_free_device(rdev); -+ kfree(itdev); -+ -+ return ret; -+} -+ -+static void __devexit ite_remove(struct pnp_dev *pdev) -+{ -+ struct ite_dev *dev = pnp_get_drvdata(pdev); -+ unsigned long flags; -+ -+ ite_dbg("%s called", __func__); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* disable hardware */ -+ dev->params.disable(dev); -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ /* free resources */ -+ free_irq(dev->cir_irq, dev); -+ release_region(dev->cir_addr, dev->params.io_region_size); -+ -+ rc_unregister_device(dev->rdev); -+ -+ kfree(dev); -+} -+ -+static int ite_suspend(struct pnp_dev *pdev, pm_message_t state) -+{ -+ struct ite_dev *dev = pnp_get_drvdata(pdev); -+ unsigned long flags; -+ -+ ite_dbg("%s called", __func__); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* disable all interrupts */ -+ dev->params.disable(dev); -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return 0; -+} -+ -+static int ite_resume(struct pnp_dev *pdev) -+{ -+ int ret = 0; -+ struct ite_dev *dev = pnp_get_drvdata(pdev); -+ unsigned long flags; -+ -+ ite_dbg("%s called", __func__); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ if (dev->transmitting) { -+ /* wake up the transmitter */ -+ wake_up_interruptible(&dev->tx_queue); -+ } else { -+ /* enable the receiver */ -+ dev->params.enable_rx(dev); -+ } -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+ -+ return ret; -+} -+ -+static void ite_shutdown(struct pnp_dev *pdev) -+{ -+ struct ite_dev *dev = pnp_get_drvdata(pdev); -+ unsigned long flags; -+ -+ ite_dbg("%s called", __func__); -+ -+ spin_lock_irqsave(&dev->lock, flags); -+ -+ /* disable all interrupts */ -+ dev->params.disable(dev); -+ -+ spin_unlock_irqrestore(&dev->lock, flags); -+} -+ -+static struct pnp_driver ite_driver = { -+ .name = ITE_DRIVER_NAME, -+ .id_table = ite_ids, -+ .probe = ite_probe, -+ .remove = __devexit_p(ite_remove), -+ .suspend = ite_suspend, -+ .resume = ite_resume, -+ .shutdown = ite_shutdown, -+}; -+ -+int ite_init(void) -+{ -+ return pnp_register_driver(&ite_driver); -+} -+ -+void ite_exit(void) -+{ -+ pnp_unregister_driver(&ite_driver); -+} -+ -+MODULE_DEVICE_TABLE(pnp, ite_ids); -+MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver"); -+ -+MODULE_AUTHOR("Juan J. Garcia de Soria "); -+MODULE_LICENSE("GPL"); -+ -+module_init(ite_init); -+module_exit(ite_exit); -diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h -new file mode 100644 -index 0000000..16a19f5 ---- /dev/null -+++ b/drivers/media/rc/ite-cir.h -@@ -0,0 +1,481 @@ -+/* -+ * Driver for ITE Tech Inc. IT8712F/IT8512F CIR -+ * -+ * Copyright (C) 2010 Juan Jesús García de Soria -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ * USA. -+ */ -+ -+/* platform driver name to register */ -+#define ITE_DRIVER_NAME "ite-cir" -+ -+/* logging macros */ -+#define ite_pr(level, text, ...) \ -+ printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) -+#define ite_dbg(text, ...) do { \ -+ if (debug) \ -+ printk(KERN_DEBUG \ -+ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \ -+} while (0) -+ -+#define ite_dbg_verbose(text, ...) do {\ -+ if (debug > 1) \ -+ printk(KERN_DEBUG \ -+ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \ -+} while (0) -+ -+/* FIFO sizes */ -+#define ITE_TX_FIFO_LEN 32 -+#define ITE_RX_FIFO_LEN 32 -+ -+/* interrupt types */ -+#define ITE_IRQ_TX_FIFO 1 -+#define ITE_IRQ_RX_FIFO 2 -+#define ITE_IRQ_RX_FIFO_OVERRUN 4 -+ -+/* forward declaration */ -+struct ite_dev; -+ -+/* struct for storing the parameters of different recognized devices */ -+struct ite_dev_params { -+ /* model of the device */ -+ const char *model; -+ -+ /* size of the I/O region */ -+ int io_region_size; -+ -+ /* true if the hardware supports transmission */ -+ bool hw_tx_capable; -+ -+ /* base sampling period, in ns */ -+ u32 sample_period; -+ -+ /* rx low carrier frequency, in Hz, 0 means no demodulation */ -+ unsigned int rx_low_carrier_freq; -+ -+ /* tx high carrier frequency, in Hz, 0 means no demodulation */ -+ unsigned int rx_high_carrier_freq; -+ -+ /* tx carrier frequency, in Hz */ -+ unsigned int tx_carrier_freq; -+ -+ /* duty cycle, 0-100 */ -+ int tx_duty_cycle; -+ -+ /* hw-specific operation function pointers; most of these must be -+ * called while holding the spin lock, except for the TX FIFO length -+ * one */ -+ /* get pending interrupt causes */ -+ int (*get_irq_causes) (struct ite_dev *dev); -+ -+ /* enable rx */ -+ void (*enable_rx) (struct ite_dev *dev); -+ -+ /* make rx enter the idle state; keep listening for a pulse, but stop -+ * streaming space bytes */ -+ void (*idle_rx) (struct ite_dev *dev); -+ -+ /* disable rx completely */ -+ void (*disable_rx) (struct ite_dev *dev); -+ -+ /* read bytes from RX FIFO; return read count */ -+ int (*get_rx_bytes) (struct ite_dev *dev, u8 *buf, int buf_size); -+ -+ /* enable tx FIFO space available interrupt */ -+ void (*enable_tx_interrupt) (struct ite_dev *dev); -+ -+ /* disable tx FIFO space available interrupt */ -+ void (*disable_tx_interrupt) (struct ite_dev *dev); -+ -+ /* get number of full TX FIFO slots */ -+ int (*get_tx_used_slots) (struct ite_dev *dev); -+ -+ /* put a byte to the TX FIFO */ -+ void (*put_tx_byte) (struct ite_dev *dev, u8 value); -+ -+ /* disable hardware completely */ -+ void (*disable) (struct ite_dev *dev); -+ -+ /* initialize the hardware */ -+ void (*init_hardware) (struct ite_dev *dev); -+ -+ /* set the carrier parameters */ -+ void (*set_carrier_params) (struct ite_dev *dev, bool high_freq, -+ bool use_demodulator, u8 carrier_freq_bits, -+ u8 allowance_bits, u8 pulse_width_bits); -+}; -+ -+/* ITE CIR device structure */ -+struct ite_dev { -+ struct pnp_dev *pdev; -+ struct rc_dev *rdev; -+ struct ir_raw_event rawir; -+ -+ /* sync data */ -+ spinlock_t lock; -+ bool in_use, transmitting; -+ -+ /* transmit support */ -+ int tx_fifo_allowance; -+ wait_queue_head_t tx_queue, tx_ended; -+ -+ /* hardware I/O settings */ -+ unsigned long cir_addr; -+ int cir_irq; -+ -+ /* overridable copy of model parameters */ -+ struct ite_dev_params params; -+}; -+ -+/* common values for all kinds of hardware */ -+ -+/* baud rate divisor default */ -+#define ITE_BAUDRATE_DIVISOR 1 -+ -+/* low-speed carrier frequency limits (Hz) */ -+#define ITE_LCF_MIN_CARRIER_FREQ 27000 -+#define ITE_LCF_MAX_CARRIER_FREQ 58000 -+ -+/* high-speed carrier frequency limits (Hz) */ -+#define ITE_HCF_MIN_CARRIER_FREQ 400000 -+#define ITE_HCF_MAX_CARRIER_FREQ 500000 -+ -+/* default carrier freq for when demodulator is off (Hz) */ -+#define ITE_DEFAULT_CARRIER_FREQ 38000 -+ -+/* default idling timeout in ns (0.2 seconds) */ -+#define ITE_IDLE_TIMEOUT 200000000UL -+ -+/* limit timeout values */ -+#define ITE_MIN_IDLE_TIMEOUT 100000000UL -+#define ITE_MAX_IDLE_TIMEOUT 1000000000UL -+ -+/* convert bits to us */ -+#define ITE_BITS_TO_NS(bits, sample_period) \ -+((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period)) -+ -+/* -+ * n in RDCR produces a tolerance of +/- n * 6.25% around the center -+ * carrier frequency... -+ * -+ * From two limit frequencies, L (low) and H (high), we can get both the -+ * center frequency F = (L + H) / 2 and the variation from the center -+ * frequency A = (H - L) / (H + L). We can use this in order to honor the -+ * s_rx_carrier_range() call in ir-core. We'll suppose that any request -+ * setting L=0 means we must shut down the demodulator. -+ */ -+#define ITE_RXDCR_PER_10000_STEP 625 -+ -+/* high speed carrier freq values */ -+#define ITE_CFQ_400 0x03 -+#define ITE_CFQ_450 0x08 -+#define ITE_CFQ_480 0x0b -+#define ITE_CFQ_500 0x0d -+ -+/* values for pulse widths */ -+#define ITE_TXMPW_A 0x02 -+#define ITE_TXMPW_B 0x03 -+#define ITE_TXMPW_C 0x04 -+#define ITE_TXMPW_D 0x05 -+#define ITE_TXMPW_E 0x06 -+ -+/* values for demodulator carrier range allowance */ -+#define ITE_RXDCR_DEFAULT 0x01 /* default carrier range */ -+#define ITE_RXDCR_MAX 0x07 /* default carrier range */ -+ -+/* DR TX bits */ -+#define ITE_TX_PULSE 0x00 -+#define ITE_TX_SPACE 0x80 -+#define ITE_TX_MAX_RLE 0x80 -+#define ITE_TX_RLE_MASK 0x7f -+ -+/* -+ * IT8712F -+ * -+ * hardware data obtained from: -+ * -+ * IT8712F -+ * Environment Control – Low Pin Count Input / Output -+ * (EC - LPC I/O) -+ * Preliminary Specification V0. 81 -+ */ -+ -+/* register offsets */ -+#define IT87_DR 0x00 /* data register */ -+#define IT87_IER 0x01 /* interrupt enable register */ -+#define IT87_RCR 0x02 /* receiver control register */ -+#define IT87_TCR1 0x03 /* transmitter control register 1 */ -+#define IT87_TCR2 0x04 /* transmitter control register 2 */ -+#define IT87_TSR 0x05 /* transmitter status register */ -+#define IT87_RSR 0x06 /* receiver status register */ -+#define IT87_BDLR 0x05 /* baud rate divisor low byte register */ -+#define IT87_BDHR 0x06 /* baud rate divisor high byte register */ -+#define IT87_IIR 0x07 /* interrupt identification register */ -+ -+#define IT87_IOREG_LENGTH 0x08 /* length of register file */ -+ -+/* IER bits */ -+#define IT87_TLDLIE 0x01 /* transmitter low data interrupt enable */ -+#define IT87_RDAIE 0x02 /* receiver data available interrupt enable */ -+#define IT87_RFOIE 0x04 /* receiver FIFO overrun interrupt enable */ -+#define IT87_IEC 0x08 /* interrupt enable control */ -+#define IT87_BR 0x10 /* baud rate register enable */ -+#define IT87_RESET 0x20 /* reset */ -+ -+/* RCR bits */ -+#define IT87_RXDCR 0x07 /* receiver demodulation carrier range mask */ -+#define IT87_RXACT 0x08 /* receiver active */ -+#define IT87_RXEND 0x10 /* receiver demodulation enable */ -+#define IT87_RXEN 0x20 /* receiver enable */ -+#define IT87_HCFS 0x40 /* high-speed carrier frequency select */ -+#define IT87_RDWOS 0x80 /* receiver data without sync */ -+ -+/* TCR1 bits */ -+#define IT87_TXMPM 0x03 /* transmitter modulation pulse mode mask */ -+#define IT87_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */ -+#define IT87_TXENDF 0x04 /* transmitter deferral */ -+#define IT87_TXRLE 0x08 /* transmitter run length enable */ -+#define IT87_FIFOTL 0x30 /* FIFO level threshold mask */ -+#define IT87_FIFOTL_DEFAULT 0x20 /* FIFO level threshold default -+ * 0x00 -> 1, 0x10 -> 7, 0x20 -> 17, -+ * 0x30 -> 25 */ -+#define IT87_ILE 0x40 /* internal loopback enable */ -+#define IT87_FIFOCLR 0x80 /* FIFO clear bit */ -+ -+/* TCR2 bits */ -+#define IT87_TXMPW 0x07 /* transmitter modulation pulse width mask */ -+#define IT87_TXMPW_DEFAULT 0x04 /* default modulation pulse width */ -+#define IT87_CFQ 0xf8 /* carrier frequency mask */ -+#define IT87_CFQ_SHIFT 3 /* carrier frequency bit shift */ -+ -+/* TSR bits */ -+#define IT87_TXFBC 0x3f /* transmitter FIFO byte count mask */ -+ -+/* RSR bits */ -+#define IT87_RXFBC 0x3f /* receiver FIFO byte count mask */ -+#define IT87_RXFTO 0x80 /* receiver FIFO time-out */ -+ -+/* IIR bits */ -+#define IT87_IP 0x01 /* interrupt pending */ -+#define IT87_II 0x06 /* interrupt identification mask */ -+#define IT87_II_NOINT 0x00 /* no interrupt */ -+#define IT87_II_TXLDL 0x02 /* transmitter low data level */ -+#define IT87_II_RXDS 0x04 /* receiver data stored */ -+#define IT87_II_RXFO 0x06 /* receiver FIFO overrun */ -+ -+/* -+ * IT8512E/F -+ * -+ * Hardware data obtained from: -+ * -+ * IT8512E/F -+ * Embedded Controller -+ * Preliminary Specification V0.4.1 -+ * -+ * Note that the CIR registers are not directly available to the host, because -+ * they only are accessible to the integrated microcontroller. Thus, in order -+ * use it, some kind of bridging is required. As the bridging may depend on -+ * the controller firmware in use, we are going to use the PNP ID in order to -+ * determine the strategy and ports available. See after these generic -+ * IT8512E/F register definitions for register definitions for those -+ * strategies. -+ */ -+ -+/* register offsets */ -+#define IT85_C0DR 0x00 /* data register */ -+#define IT85_C0MSTCR 0x01 /* master control register */ -+#define IT85_C0IER 0x02 /* interrupt enable register */ -+#define IT85_C0IIR 0x03 /* interrupt identification register */ -+#define IT85_C0CFR 0x04 /* carrier frequency register */ -+#define IT85_C0RCR 0x05 /* receiver control register */ -+#define IT85_C0TCR 0x06 /* transmitter control register */ -+#define IT85_C0SCK 0x07 /* slow clock control register */ -+#define IT85_C0BDLR 0x08 /* baud rate divisor low byte register */ -+#define IT85_C0BDHR 0x09 /* baud rate divisor high byte register */ -+#define IT85_C0TFSR 0x0a /* transmitter FIFO status register */ -+#define IT85_C0RFSR 0x0b /* receiver FIFO status register */ -+#define IT85_C0WCL 0x0d /* wakeup code length register */ -+#define IT85_C0WCR 0x0e /* wakeup code read/write register */ -+#define IT85_C0WPS 0x0f /* wakeup power control/status register */ -+ -+#define IT85_IOREG_LENGTH 0x10 /* length of register file */ -+ -+/* C0MSTCR bits */ -+#define IT85_RESET 0x01 /* reset */ -+#define IT85_FIFOCLR 0x02 /* FIFO clear bit */ -+#define IT85_FIFOTL 0x0c /* FIFO level threshold mask */ -+#define IT85_FIFOTL_DEFAULT 0x08 /* FIFO level threshold default -+ * 0x00 -> 1, 0x04 -> 7, 0x08 -> 17, -+ * 0x0c -> 25 */ -+#define IT85_ILE 0x10 /* internal loopback enable */ -+#define IT85_ILSEL 0x20 /* internal loopback select */ -+ -+/* C0IER bits */ -+#define IT85_TLDLIE 0x01 /* TX low data level interrupt enable */ -+#define IT85_RDAIE 0x02 /* RX data available interrupt enable */ -+#define IT85_RFOIE 0x04 /* RX FIFO overrun interrupt enable */ -+#define IT85_IEC 0x80 /* interrupt enable function control */ -+ -+/* C0IIR bits */ -+#define IT85_TLDLI 0x01 /* transmitter low data level interrupt */ -+#define IT85_RDAI 0x02 /* receiver data available interrupt */ -+#define IT85_RFOI 0x04 /* receiver FIFO overrun interrupt */ -+#define IT85_NIP 0x80 /* no interrupt pending */ -+ -+/* C0CFR bits */ -+#define IT85_CFQ 0x1f /* carrier frequency mask */ -+#define IT85_HCFS 0x20 /* high speed carrier frequency select */ -+ -+/* C0RCR bits */ -+#define IT85_RXDCR 0x07 /* receiver demodulation carrier range mask */ -+#define IT85_RXACT 0x08 /* receiver active */ -+#define IT85_RXEND 0x10 /* receiver demodulation enable */ -+#define IT85_RDWOS 0x20 /* receiver data without sync */ -+#define IT85_RXEN 0x80 /* receiver enable */ -+ -+/* C0TCR bits */ -+#define IT85_TXMPW 0x07 /* transmitter modulation pulse width mask */ -+#define IT85_TXMPW_DEFAULT 0x04 /* default modulation pulse width */ -+#define IT85_TXMPM 0x18 /* transmitter modulation pulse mode mask */ -+#define IT85_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */ -+#define IT85_TXENDF 0x20 /* transmitter deferral */ -+#define IT85_TXRLE 0x40 /* transmitter run length enable */ -+ -+/* C0SCK bits */ -+#define IT85_SCKS 0x01 /* slow clock select */ -+#define IT85_TXDCKG 0x02 /* TXD clock gating */ -+#define IT85_DLL1P8E 0x04 /* DLL 1.8432M enable */ -+#define IT85_DLLTE 0x08 /* DLL test enable */ -+#define IT85_BRCM 0x70 /* baud rate count mode */ -+#define IT85_DLLOCK 0x80 /* DLL lock */ -+ -+/* C0TFSR bits */ -+#define IT85_TXFBC 0x3f /* transmitter FIFO count mask */ -+ -+/* C0RFSR bits */ -+#define IT85_RXFBC 0x3f /* receiver FIFO count mask */ -+#define IT85_RXFTO 0x80 /* receiver FIFO time-out */ -+ -+/* C0WCL bits */ -+#define IT85_WCL 0x3f /* wakeup code length mask */ -+ -+/* C0WPS bits */ -+#define IT85_CIRPOSIE 0x01 /* power on/off status interrupt enable */ -+#define IT85_CIRPOIS 0x02 /* power on/off interrupt status */ -+#define IT85_CIRPOII 0x04 /* power on/off interrupt identification */ -+#define IT85_RCRST 0x10 /* wakeup code reading counter reset bit */ -+#define IT85_WCRST 0x20 /* wakeup code writing counter reset bit */ -+ -+/* -+ * ITE8708 -+ * -+ * Hardware data obtained from hacked driver for IT8512 in this forum post: -+ * -+ * http://ubuntuforums.org/showthread.php?t=1028640 -+ * -+ * Although there's no official documentation for that driver, analysis would -+ * suggest that it maps the 16 registers of IT8512 onto two 8-register banks, -+ * selectable by a single bank-select bit that's mapped onto both banks. The -+ * IT8512 registers are mapped in a different order, so that the first bank -+ * maps the ones that are used more often, and two registers that share a -+ * reserved high-order bit are placed at the same offset in both banks in -+ * order to reuse the reserved bit as the bank select bit. -+ */ -+ -+/* register offsets */ -+ -+/* mapped onto both banks */ -+#define IT8708_BANKSEL 0x07 /* bank select register */ -+#define IT8708_HRAE 0x80 /* high registers access enable */ -+ -+/* mapped onto the low bank */ -+#define IT8708_C0DR 0x00 /* data register */ -+#define IT8708_C0MSTCR 0x01 /* master control register */ -+#define IT8708_C0IER 0x02 /* interrupt enable register */ -+#define IT8708_C0IIR 0x03 /* interrupt identification register */ -+#define IT8708_C0RFSR 0x04 /* receiver FIFO status register */ -+#define IT8708_C0RCR 0x05 /* receiver control register */ -+#define IT8708_C0TFSR 0x06 /* transmitter FIFO status register */ -+#define IT8708_C0TCR 0x07 /* transmitter control register */ -+ -+/* mapped onto the high bank */ -+#define IT8708_C0BDLR 0x01 /* baud rate divisor low byte register */ -+#define IT8708_C0BDHR 0x02 /* baud rate divisor high byte register */ -+#define IT8708_C0CFR 0x04 /* carrier frequency register */ -+ -+/* registers whose bank mapping we don't know, since they weren't being used -+ * in the hacked driver... most probably they belong to the high bank too, -+ * since they fit in the holes the other registers leave */ -+#define IT8708_C0SCK 0x03 /* slow clock control register */ -+#define IT8708_C0WCL 0x05 /* wakeup code length register */ -+#define IT8708_C0WCR 0x06 /* wakeup code read/write register */ -+#define IT8708_C0WPS 0x07 /* wakeup power control/status register */ -+ -+#define IT8708_IOREG_LENGTH 0x08 /* length of register file */ -+ -+/* two more registers that are defined in the hacked driver, but can't be -+ * found in the data sheets; no idea what they are or how they are accessed, -+ * since the hacked driver doesn't seem to use them */ -+#define IT8708_CSCRR 0x00 -+#define IT8708_CGPINTR 0x01 -+ -+/* CSCRR bits */ -+#define IT8708_CSCRR_SCRB 0x3f -+#define IT8708_CSCRR_PM 0x80 -+ -+/* CGPINTR bits */ -+#define IT8708_CGPINT 0x01 -+ -+/* -+ * ITE8709 -+ * -+ * Hardware interfacing data obtained from the original lirc_ite8709 driver. -+ * Verbatim from its sources: -+ * -+ * The ITE8709 device seems to be the combination of IT8512 superIO chip and -+ * a specific firmware running on the IT8512's embedded micro-controller. -+ * In addition of the embedded micro-controller, the IT8512 chip contains a -+ * CIR module and several other modules. A few modules are directly accessible -+ * by the host CPU, but most of them are only accessible by the -+ * micro-controller. The CIR module is only accessible by the -+ * micro-controller. -+ * -+ * The battery-backed SRAM module is accessible by the host CPU and the -+ * micro-controller. So one of the MC's firmware role is to act as a bridge -+ * between the host CPU and the CIR module. The firmware implements a kind of -+ * communication protocol using the SRAM module as a shared memory. The IT8512 -+ * specification is publicly available on ITE's web site, but the -+ * communication protocol is not, so it was reverse-engineered. -+ */ -+ -+/* register offsets */ -+#define IT8709_RAM_IDX 0x00 /* index into the SRAM module bytes */ -+#define IT8709_RAM_VAL 0x01 /* read/write data to the indexed byte */ -+ -+#define IT8709_IOREG_LENGTH 0x02 /* length of register file */ -+ -+/* register offsets inside the SRAM module */ -+#define IT8709_MODE 0x1a /* request/ack byte */ -+#define IT8709_REG_IDX 0x1b /* index of the CIR register to access */ -+#define IT8709_REG_VAL 0x1c /* value read/to be written */ -+#define IT8709_IIR 0x1e /* interrupt identification register */ -+#define IT8709_RFSR 0x1f /* receiver FIFO status register */ -+#define IT8709_FIFO 0x20 /* start of in RAM RX FIFO copy */ -+ -+/* MODE values */ -+#define IT8709_IDLE 0x00 -+#define IT8709_WRITE 0x01 -+#define IT8709_READ 0x02 -diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile -index cb72121..85cac7d 100644 ---- a/drivers/media/rc/keymaps/Makefile -+++ b/drivers/media/rc/keymaps/Makefile -@@ -37,7 +37,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-gadmei-rm008z.o \ - rc-genius-tvgo-a11mce.o \ - rc-gotview7135.o \ -- rc-hauppauge-new.o \ - rc-imon-mce.o \ - rc-imon-pad.o \ - rc-iodata-bctv7e.o \ -@@ -68,8 +67,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ - rc-proteus-2309.o \ - rc-purpletv.o \ - rc-pv951.o \ -- rc-rc5-hauppauge-new.o \ -- rc-rc5-tv.o \ -+ rc-hauppauge.o \ - rc-rc6-mce.o \ - rc-real-audio-220-32-keys.o \ - rc-streamzap.o \ -diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c -index 136d395..9a8752f 100644 ---- a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c -+++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c -@@ -50,9 +50,9 @@ static struct rc_map_table adstech_dvb_t_pci[] = { - { 0x13, KEY_TUNER }, /* Live */ - { 0x0a, KEY_A }, - { 0x12, KEY_B }, -- { 0x03, KEY_PROG1 }, /* 1 */ -- { 0x01, KEY_PROG2 }, /* 2 */ -- { 0x00, KEY_PROG3 }, /* 3 */ -+ { 0x03, KEY_RED }, /* 1 */ -+ { 0x01, KEY_GREEN }, /* 2 */ -+ { 0x00, KEY_YELLOW }, /* 3 */ - { 0x06, KEY_DVD }, - { 0x48, KEY_AUX }, /* Photo */ - { 0x40, KEY_VIDEO }, -diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c -index 3ddb41b..c25809d 100644 ---- a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c -+++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c -@@ -26,12 +26,12 @@ static struct rc_map_table avermedia_dvbt[] = { - { 0x16, KEY_8 }, /* '8' / 'down arrow' */ - { 0x36, KEY_9 }, /* '9' */ - -- { 0x20, KEY_LIST }, /* 'source' */ -+ { 0x20, KEY_VIDEO }, /* 'source' */ - { 0x10, KEY_TEXT }, /* 'teletext' */ - { 0x00, KEY_POWER }, /* 'power' */ - { 0x04, KEY_AUDIO }, /* 'audio' */ - { 0x06, KEY_ZOOM }, /* 'full screen' */ -- { 0x18, KEY_VIDEO }, /* 'display' */ -+ { 0x18, KEY_SWITCHVIDEOMODE }, /* 'display' */ - { 0x38, KEY_SEARCH }, /* 'loop' */ - { 0x08, KEY_INFO }, /* 'preview' */ - { 0x2a, KEY_REWIND }, /* 'backward <<' */ -diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c -index 357fea5..3d2cbe4 100644 ---- a/drivers/media/rc/keymaps/rc-avermedia-m135a.c -+++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c -@@ -108,7 +108,7 @@ static struct rc_map_table avermedia_m135a[] = { - { 0x0414, KEY_TEXT }, - { 0x0415, KEY_EPG }, - { 0x041a, KEY_TV2 }, /* PIP */ -- { 0x041b, KEY_MHP }, /* Snapshot */ -+ { 0x041b, KEY_CAMERA }, /* Snapshot */ - - { 0x0417, KEY_RECORD }, - { 0x0416, KEY_PLAYPAUSE }, -diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c -index e694e6e..8cd7f28 100644 ---- a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c -+++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c -@@ -56,7 +56,7 @@ static struct rc_map_table avermedia_m733a_rm_k6[] = { - { 0x0414, KEY_TEXT }, - { 0x0415, KEY_EPG }, - { 0x041a, KEY_TV2 }, /* PIP */ -- { 0x041b, KEY_MHP }, /* Snapshot */ -+ { 0x041b, KEY_CAMERA }, /* Snapshot */ - - { 0x0417, KEY_RECORD }, - { 0x0416, KEY_PLAYPAUSE }, -diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c -index f4ca1ff..9d68af2 100644 ---- a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c -+++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c -@@ -31,7 +31,7 @@ static struct rc_map_table avermedia_rm_ks[] = { - { 0x0505, KEY_VOLUMEDOWN }, - { 0x0506, KEY_MUTE }, - { 0x0507, KEY_RIGHT }, -- { 0x0508, KEY_PROG1 }, -+ { 0x0508, KEY_RED }, - { 0x0509, KEY_1 }, - { 0x050a, KEY_2 }, - { 0x050b, KEY_3 }, -diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c -index 4b787fa..8bf058f 100644 ---- a/drivers/media/rc/keymaps/rc-behold-columbus.c -+++ b/drivers/media/rc/keymaps/rc-behold-columbus.c -@@ -28,7 +28,7 @@ static struct rc_map_table behold_columbus[] = { - * */ - - { 0x13, KEY_MUTE }, -- { 0x11, KEY_PROPS }, -+ { 0x11, KEY_VIDEO }, - { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ - { 0x12, KEY_POWER }, - -diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c -index 0ee1f14..c909a23 100644 ---- a/drivers/media/rc/keymaps/rc-behold.c -+++ b/drivers/media/rc/keymaps/rc-behold.c -@@ -97,7 +97,7 @@ static struct rc_map_table behold[] = { - { 0x6b861a, KEY_STOP }, - { 0x6b860e, KEY_TEXT }, - { 0x6b861f, KEY_RED }, /*XXX KEY_AUDIO */ -- { 0x6b861e, KEY_YELLOW }, /*XXX KEY_SOURCE */ -+ { 0x6b861e, KEY_VIDEO }, - - /* 0x1d 0x13 0x19 * - * SLEEP PREVIEW DVB * -diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c -index 97fc386..2f66e43 100644 ---- a/drivers/media/rc/keymaps/rc-budget-ci-old.c -+++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c -@@ -12,7 +12,8 @@ - - #include - --/* From reading the following remotes: -+/* -+ * From reading the following remotes: - * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 - * Hauppauge (from NOVA-CI-s box product) - * This is a "middle of the road" approach, differences are noted -diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c -index 99520ff..cf3a6bf 100644 ---- a/drivers/media/rc/keymaps/rc-cinergy.c -+++ b/drivers/media/rc/keymaps/rc-cinergy.c -@@ -25,7 +25,7 @@ static struct rc_map_table cinergy[] = { - { 0x09, KEY_9 }, - - { 0x0a, KEY_POWER }, -- { 0x0b, KEY_PROG1 }, /* app */ -+ { 0x0b, KEY_MEDIA }, /* app */ - { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ - { 0x0d, KEY_CHANNELUP }, /* channel */ - { 0x0e, KEY_CHANNELDOWN }, /* channel- */ -diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c -index 43912bd..82c0200 100644 ---- a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c -+++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c -@@ -32,7 +32,7 @@ static struct rc_map_table dntv_live_dvb_t[] = { - { 0x0c, KEY_SEARCH }, /* scan */ - { 0x0d, KEY_STOP }, - { 0x0e, KEY_PAUSE }, -- { 0x0f, KEY_LIST }, /* source */ -+ { 0x0f, KEY_VIDEO }, /* source */ - - { 0x10, KEY_MUTE }, - { 0x11, KEY_REWIND }, /* backward << */ -diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c -index afa4e92..e56ac6e 100644 ---- a/drivers/media/rc/keymaps/rc-encore-enltv.c -+++ b/drivers/media/rc/keymaps/rc-encore-enltv.c -@@ -24,7 +24,7 @@ static struct rc_map_table encore_enltv[] = { - { 0x1e, KEY_TV }, - { 0x00, KEY_VIDEO }, - { 0x01, KEY_AUDIO }, /* music */ -- { 0x02, KEY_MHP }, /* picture */ -+ { 0x02, KEY_CAMERA }, /* picture */ - - { 0x1f, KEY_1 }, - { 0x03, KEY_2 }, -@@ -77,7 +77,7 @@ static struct rc_map_table encore_enltv[] = { - { 0x50, KEY_SLEEP }, /* shutdown */ - { 0x51, KEY_MODE }, /* stereo > main */ - { 0x52, KEY_SELECT }, /* stereo > sap */ -- { 0x53, KEY_PROG1 }, /* teletext */ -+ { 0x53, KEY_TEXT }, /* teletext */ - - - { 0x59, KEY_RED }, /* AP1 */ -diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c -index 7d5b00e..b6264f1 100644 ---- a/drivers/media/rc/keymaps/rc-encore-enltv2.c -+++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c -@@ -32,7 +32,7 @@ static struct rc_map_table encore_enltv2[] = { - { 0x64, KEY_LAST }, /* +100 */ - { 0x4e, KEY_AGAIN }, /* Recall */ - -- { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ -+ { 0x6c, KEY_VIDEO }, /* Video Source */ - { 0x5e, KEY_MENU }, - { 0x56, KEY_SCREEN }, - { 0x7a, KEY_SETUP }, -diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c -index aea2f4a..a8b0f66 100644 ---- a/drivers/media/rc/keymaps/rc-flydvb.c -+++ b/drivers/media/rc/keymaps/rc-flydvb.c -@@ -37,8 +37,8 @@ static struct rc_map_table flydvb[] = { - { 0x13, KEY_CHANNELDOWN }, /* CH- */ - { 0x1d, KEY_ENTER }, /* Enter */ - -- { 0x1a, KEY_MODE }, /* PIP */ -- { 0x18, KEY_TUNER }, /* Source */ -+ { 0x1a, KEY_TV2 }, /* PIP */ -+ { 0x18, KEY_VIDEO }, /* Source */ - - { 0x1e, KEY_RECORD }, /* Record/Pause */ - { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ -diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c -deleted file mode 100644 -index bd11da4..0000000 ---- a/drivers/media/rc/keymaps/rc-hauppauge-new.c -+++ /dev/null -@@ -1,100 +0,0 @@ --/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller -- * -- * keymap imported from ir-keymaps.c -- * -- * Copyright (c) 2010 by Mauro Carvalho Chehab -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- */ -- --#include -- --/* Hauppauge: the newer, gray remotes (seems there are multiple -- * slightly different versions), shipped with cx88+ivtv cards. -- * almost rc5 coding, but some non-standard keys */ -- --static struct rc_map_table hauppauge_new[] = { -- /* Keys 0 to 9 */ -- { 0x00, KEY_0 }, -- { 0x01, KEY_1 }, -- { 0x02, KEY_2 }, -- { 0x03, KEY_3 }, -- { 0x04, KEY_4 }, -- { 0x05, KEY_5 }, -- { 0x06, KEY_6 }, -- { 0x07, KEY_7 }, -- { 0x08, KEY_8 }, -- { 0x09, KEY_9 }, -- -- { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ -- { 0x0b, KEY_RED }, /* red button */ -- { 0x0c, KEY_RADIO }, -- { 0x0d, KEY_MENU }, -- { 0x0e, KEY_SUBTITLE }, /* also the # key */ -- { 0x0f, KEY_MUTE }, -- { 0x10, KEY_VOLUMEUP }, -- { 0x11, KEY_VOLUMEDOWN }, -- { 0x12, KEY_PREVIOUS }, /* previous channel */ -- { 0x14, KEY_UP }, -- { 0x15, KEY_DOWN }, -- { 0x16, KEY_LEFT }, -- { 0x17, KEY_RIGHT }, -- { 0x18, KEY_VIDEO }, /* Videos */ -- { 0x19, KEY_AUDIO }, /* Music */ -- /* 0x1a: Pictures - presume this means -- "Multimedia Home Platform" - -- no "PICTURES" key in input.h -- */ -- { 0x1a, KEY_MHP }, -- -- { 0x1b, KEY_EPG }, /* Guide */ -- { 0x1c, KEY_TV }, -- { 0x1e, KEY_NEXTSONG }, /* skip >| */ -- { 0x1f, KEY_EXIT }, /* back/exit */ -- { 0x20, KEY_CHANNELUP }, /* channel / program + */ -- { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ -- { 0x22, KEY_CHANNEL }, /* source (old black remote) */ -- { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ -- { 0x25, KEY_ENTER }, /* OK */ -- { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ -- { 0x29, KEY_BLUE }, /* blue key */ -- { 0x2e, KEY_GREEN }, /* green button */ -- { 0x30, KEY_PAUSE }, /* pause */ -- { 0x32, KEY_REWIND }, /* backward << */ -- { 0x34, KEY_FASTFORWARD }, /* forward >> */ -- { 0x35, KEY_PLAY }, -- { 0x36, KEY_STOP }, -- { 0x37, KEY_RECORD }, /* recording */ -- { 0x38, KEY_YELLOW }, /* yellow key */ -- { 0x3b, KEY_SELECT }, /* top right button */ -- { 0x3c, KEY_ZOOM }, /* full */ -- { 0x3d, KEY_POWER }, /* system power (green button) */ --}; -- --static struct rc_map_list hauppauge_new_map = { -- .map = { -- .scan = hauppauge_new, -- .size = ARRAY_SIZE(hauppauge_new), -- .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ -- .name = RC_MAP_HAUPPAUGE_NEW, -- } --}; -- --static int __init init_rc_map_hauppauge_new(void) --{ -- return rc_map_register(&hauppauge_new_map); --} -- --static void __exit exit_rc_map_hauppauge_new(void) --{ -- rc_map_unregister(&hauppauge_new_map); --} -- --module_init(init_rc_map_hauppauge_new) --module_exit(exit_rc_map_hauppauge_new) -- --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Mauro Carvalho Chehab "); -diff --git a/drivers/media/rc/keymaps/rc-hauppauge.c b/drivers/media/rc/keymaps/rc-hauppauge.c -new file mode 100644 -index 0000000..cd3db77 ---- /dev/null -+++ b/drivers/media/rc/keymaps/rc-hauppauge.c -@@ -0,0 +1,241 @@ -+/* rc-hauppauge.c - Keytable for Hauppauge Remote Controllers -+ * -+ * keymap imported from ir-keymaps.c -+ * -+ * This map currently contains the code for four different RCs: -+ * - New Hauppauge Gray; -+ * - Old Hauppauge Gray (with a golden screen for media keys); -+ * - Hauppauge Black; -+ * - DSR-0112 remote bundled with Haupauge MiniStick. -+ * -+ * Copyright (c) 2010-2011 by Mauro Carvalho Chehab -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+ -+/* -+ * Hauppauge:the newer, gray remotes (seems there are multiple -+ * slightly different versions), shipped with cx88+ivtv cards. -+ * -+ * This table contains the complete RC5 code, instead of just the data part -+ */ -+ -+static struct rc_map_table rc5_hauppauge_new[] = { -+ /* -+ * Remote Controller Hauppauge Gray found on modern devices -+ * Keycodes start with address = 0x1e -+ */ -+ -+ { 0x1e3b, KEY_SELECT }, /* GO / house symbol */ -+ { 0x1e3d, KEY_POWER2 }, /* system power (green button) */ -+ -+ { 0x1e1c, KEY_TV }, -+ { 0x1e18, KEY_VIDEO }, /* Videos */ -+ { 0x1e19, KEY_AUDIO }, /* Music */ -+ { 0x1e1a, KEY_CAMERA }, /* Pictures */ -+ -+ { 0x1e1b, KEY_EPG }, /* Guide */ -+ { 0x1e0c, KEY_RADIO }, -+ -+ { 0x1e14, KEY_UP }, -+ { 0x1e15, KEY_DOWN }, -+ { 0x1e16, KEY_LEFT }, -+ { 0x1e17, KEY_RIGHT }, -+ { 0x1e25, KEY_OK }, /* OK */ -+ -+ { 0x1e1f, KEY_EXIT }, /* back/exit */ -+ { 0x1e0d, KEY_MENU }, -+ -+ { 0x1e10, KEY_VOLUMEUP }, -+ { 0x1e11, KEY_VOLUMEDOWN }, -+ -+ { 0x1e12, KEY_PREVIOUS }, /* previous channel */ -+ { 0x1e0f, KEY_MUTE }, -+ -+ { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ -+ { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ -+ -+ { 0x1e37, KEY_RECORD }, /* recording */ -+ { 0x1e36, KEY_STOP }, -+ -+ { 0x1e32, KEY_REWIND }, /* backward << */ -+ { 0x1e35, KEY_PLAY }, -+ { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ -+ -+ { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ -+ { 0x1e30, KEY_PAUSE }, /* pause */ -+ { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ -+ -+ { 0x1e01, KEY_1 }, -+ { 0x1e02, KEY_2 }, -+ { 0x1e03, KEY_3 }, -+ -+ { 0x1e04, KEY_4 }, -+ { 0x1e05, KEY_5 }, -+ { 0x1e06, KEY_6 }, -+ -+ { 0x1e07, KEY_7 }, -+ { 0x1e08, KEY_8 }, -+ { 0x1e09, KEY_9 }, -+ -+ { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ -+ { 0x1e00, KEY_0 }, -+ { 0x1e0e, KEY_SUBTITLE }, /* also the Pound key (#) */ -+ -+ { 0x1e0b, KEY_RED }, /* red button */ -+ { 0x1e2e, KEY_GREEN }, /* green button */ -+ { 0x1e38, KEY_YELLOW }, /* yellow key */ -+ { 0x1e29, KEY_BLUE }, /* blue key */ -+ -+ /* -+ * Old Remote Controller Hauppauge Gray with a golden screen -+ * Keycodes start with address = 0x1f -+ */ -+ { 0x1f3d, KEY_POWER2 }, /* system power (green button) */ -+ { 0x1f3b, KEY_SELECT }, /* GO */ -+ -+ /* Keys 0 to 9 */ -+ { 0x1f00, KEY_0 }, -+ { 0x1f01, KEY_1 }, -+ { 0x1f02, KEY_2 }, -+ { 0x1f03, KEY_3 }, -+ { 0x1f04, KEY_4 }, -+ { 0x1f05, KEY_5 }, -+ { 0x1f06, KEY_6 }, -+ { 0x1f07, KEY_7 }, -+ { 0x1f08, KEY_8 }, -+ { 0x1f09, KEY_9 }, -+ -+ { 0x1f1f, KEY_EXIT }, /* back/exit */ -+ { 0x1f0d, KEY_MENU }, -+ -+ { 0x1f10, KEY_VOLUMEUP }, -+ { 0x1f11, KEY_VOLUMEDOWN }, -+ { 0x1f20, KEY_CHANNELUP }, /* channel / program + */ -+ { 0x1f21, KEY_CHANNELDOWN }, /* channel / program - */ -+ { 0x1f25, KEY_ENTER }, /* OK */ -+ -+ { 0x1f0b, KEY_RED }, /* red button */ -+ { 0x1f2e, KEY_GREEN }, /* green button */ -+ { 0x1f38, KEY_YELLOW }, /* yellow key */ -+ { 0x1f29, KEY_BLUE }, /* blue key */ -+ -+ { 0x1f0f, KEY_MUTE }, -+ { 0x1f0c, KEY_RADIO }, /* There's no indicator on this key */ -+ { 0x1f3c, KEY_ZOOM }, /* full */ -+ -+ { 0x1f32, KEY_REWIND }, /* backward << */ -+ { 0x1f35, KEY_PLAY }, -+ { 0x1f34, KEY_FASTFORWARD }, /* forward >> */ -+ -+ { 0x1f37, KEY_RECORD }, /* recording */ -+ { 0x1f36, KEY_STOP }, -+ { 0x1f30, KEY_PAUSE }, /* pause */ -+ -+ { 0x1f24, KEY_PREVIOUSSONG }, /* replay |< */ -+ { 0x1f1e, KEY_NEXTSONG }, /* skip >| */ -+ -+ /* -+ * Keycodes for DSR-0112 remote bundled with Haupauge MiniStick -+ * Keycodes start with address = 0x1d -+ */ -+ { 0x1d00, KEY_0 }, -+ { 0x1d01, KEY_1 }, -+ { 0x1d02, KEY_2 }, -+ { 0x1d03, KEY_3 }, -+ { 0x1d04, KEY_4 }, -+ { 0x1d05, KEY_5 }, -+ { 0x1d06, KEY_6 }, -+ { 0x1d07, KEY_7 }, -+ { 0x1d08, KEY_8 }, -+ { 0x1d09, KEY_9 }, -+ { 0x1d0a, KEY_TEXT }, -+ { 0x1d0d, KEY_MENU }, -+ { 0x1d0f, KEY_MUTE }, -+ { 0x1d10, KEY_VOLUMEUP }, -+ { 0x1d11, KEY_VOLUMEDOWN }, -+ { 0x1d12, KEY_PREVIOUS }, /* Prev.Ch .. ??? */ -+ { 0x1d14, KEY_UP }, -+ { 0x1d15, KEY_DOWN }, -+ { 0x1d16, KEY_LEFT }, -+ { 0x1d17, KEY_RIGHT }, -+ { 0x1d1c, KEY_TV }, -+ { 0x1d1e, KEY_NEXT }, /* >| */ -+ { 0x1d1f, KEY_EXIT }, -+ { 0x1d20, KEY_CHANNELUP }, -+ { 0x1d21, KEY_CHANNELDOWN }, -+ { 0x1d24, KEY_LAST }, /* <| */ -+ { 0x1d25, KEY_OK }, -+ { 0x1d30, KEY_PAUSE }, -+ { 0x1d32, KEY_REWIND }, -+ { 0x1d34, KEY_FASTFORWARD }, -+ { 0x1d35, KEY_PLAY }, -+ { 0x1d36, KEY_STOP }, -+ { 0x1d37, KEY_RECORD }, -+ { 0x1d3b, KEY_GOTO }, -+ { 0x1d3d, KEY_POWER }, -+ { 0x1d3f, KEY_HOME }, -+ -+ /* -+ * Keycodes for the old Black Remote Controller -+ * This one also uses RC-5 protocol -+ * Keycodes start with address = 0x00 -+ */ -+ { 0x001f, KEY_TV }, -+ { 0x0020, KEY_CHANNELUP }, -+ { 0x000c, KEY_RADIO }, -+ -+ { 0x0011, KEY_VOLUMEDOWN }, -+ { 0x002e, KEY_ZOOM }, /* full screen */ -+ { 0x0010, KEY_VOLUMEUP }, -+ -+ { 0x000d, KEY_MUTE }, -+ { 0x0021, KEY_CHANNELDOWN }, -+ { 0x0022, KEY_VIDEO }, /* source */ -+ -+ { 0x0001, KEY_1 }, -+ { 0x0002, KEY_2 }, -+ { 0x0003, KEY_3 }, -+ -+ { 0x0004, KEY_4 }, -+ { 0x0005, KEY_5 }, -+ { 0x0006, KEY_6 }, -+ -+ { 0x0007, KEY_7 }, -+ { 0x0008, KEY_8 }, -+ { 0x0009, KEY_9 }, -+ -+ { 0x001e, KEY_RED }, /* Reserved */ -+ { 0x0000, KEY_0 }, -+ { 0x0026, KEY_SLEEP }, /* Minimize */ -+}; -+ -+static struct rc_map_list rc5_hauppauge_new_map = { -+ .map = { -+ .scan = rc5_hauppauge_new, -+ .size = ARRAY_SIZE(rc5_hauppauge_new), -+ .rc_type = RC_TYPE_RC5, -+ .name = RC_MAP_HAUPPAUGE, -+ } -+}; -+ -+static int __init init_rc_map_rc5_hauppauge_new(void) -+{ -+ return rc_map_register(&rc5_hauppauge_new_map); -+} -+ -+static void __exit exit_rc_map_rc5_hauppauge_new(void) -+{ -+ rc_map_unregister(&rc5_hauppauge_new_map); -+} -+ -+module_init(init_rc_map_rc5_hauppauge_new) -+module_exit(exit_rc_map_rc5_hauppauge_new) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Mauro Carvalho Chehab "); -diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c -index cb67184..937a819 100644 ---- a/drivers/media/rc/keymaps/rc-imon-mce.c -+++ b/drivers/media/rc/keymaps/rc-imon-mce.c -@@ -111,7 +111,7 @@ static struct rc_map_table imon_mce[] = { - { 0x800ff44d, KEY_TITLE }, - - { 0x800ff40c, KEY_POWER }, -- { 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */ -+ { 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */ - - }; - -diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c -index eef46b7..63d42bd 100644 ---- a/drivers/media/rc/keymaps/rc-imon-pad.c -+++ b/drivers/media/rc/keymaps/rc-imon-pad.c -@@ -125,7 +125,7 @@ static struct rc_map_table imon_pad[] = { - { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ - { 0x02000065, KEY_COMPOSE }, /* RightMenu */ - { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ -- { 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */ -+ { 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */ - { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ - }; - -diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c -index 3ce6ef7..7f33edb 100644 ---- a/drivers/media/rc/keymaps/rc-kworld-315u.c -+++ b/drivers/media/rc/keymaps/rc-kworld-315u.c -@@ -17,7 +17,7 @@ - - static struct rc_map_table kworld_315u[] = { - { 0x6143, KEY_POWER }, -- { 0x6101, KEY_TUNER }, /* source */ -+ { 0x6101, KEY_VIDEO }, /* source */ - { 0x610b, KEY_ZOOM }, - { 0x6103, KEY_POWER2 }, /* shutdown */ - -diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c -index e45f0b8..08d1831 100644 ---- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c -+++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c -@@ -17,7 +17,7 @@ - */ - - static struct rc_map_table kworld_plus_tv_analog[] = { -- { 0x0c, KEY_PROG1 }, /* Kworld key */ -+ { 0x0c, KEY_LEFTMETA }, /* Kworld key */ - { 0x16, KEY_CLOSECD }, /* -> ) */ - { 0x1d, KEY_POWER2 }, - -diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c -index fa8fd0a..8e9969d 100644 ---- a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c -+++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c -@@ -62,7 +62,7 @@ static struct rc_map_table msi_tvanywhere_plus[] = { - { 0x13, KEY_AGAIN }, /* Recall */ - - { 0x1e, KEY_POWER }, /* Power */ -- { 0x07, KEY_TUNER }, /* Source */ -+ { 0x07, KEY_VIDEO }, /* Source */ - { 0x1c, KEY_SEARCH }, /* Scan */ - { 0x18, KEY_MUTE }, /* Mute */ - -diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c -index 3e6f077..ddae20e 100644 ---- a/drivers/media/rc/keymaps/rc-nebula.c -+++ b/drivers/media/rc/keymaps/rc-nebula.c -@@ -27,7 +27,7 @@ static struct rc_map_table nebula[] = { - { 0x0b, KEY_AUX }, - { 0x0c, KEY_DVD }, - { 0x0d, KEY_POWER }, -- { 0x0e, KEY_MHP }, /* labelled 'Picture' */ -+ { 0x0e, KEY_CAMERA }, /* labelled 'Picture' */ - { 0x0f, KEY_AUDIO }, - { 0x10, KEY_INFO }, - { 0x11, KEY_F13 }, /* 16:9 */ -diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c -index 629ee9d..f1c1281 100644 ---- a/drivers/media/rc/keymaps/rc-norwood.c -+++ b/drivers/media/rc/keymaps/rc-norwood.c -@@ -29,7 +29,7 @@ static struct rc_map_table norwood[] = { - { 0x28, KEY_8 }, - { 0x29, KEY_9 }, - -- { 0x78, KEY_TUNER }, /* Video Source */ -+ { 0x78, KEY_VIDEO }, /* Video Source */ - { 0x2c, KEY_EXIT }, /* Open/Close software */ - { 0x2a, KEY_SELECT }, /* 2 Digit Select */ - { 0x69, KEY_AGAIN }, /* Recall */ -diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c -index fa5ae59..7cdef6e 100644 ---- a/drivers/media/rc/keymaps/rc-pctv-sedna.c -+++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c -@@ -36,7 +36,7 @@ static struct rc_map_table pctv_sedna[] = { - { 0x0e, KEY_STOP }, - { 0x0f, KEY_PREVIOUSSONG }, - { 0x10, KEY_ZOOM }, -- { 0x11, KEY_TUNER }, /* Source */ -+ { 0x11, KEY_VIDEO }, /* Source */ - { 0x12, KEY_POWER }, - { 0x13, KEY_MUTE }, - { 0x15, KEY_CHANNELDOWN }, -diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c -index 8d9f664..125fc39 100644 ---- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c -+++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c -@@ -34,7 +34,7 @@ static struct rc_map_table pixelview_mk12[] = { - { 0x866b13, KEY_AGAIN }, /* loop */ - { 0x866b10, KEY_DIGITS }, /* +100 */ - -- { 0x866b00, KEY_MEDIA }, /* source */ -+ { 0x866b00, KEY_VIDEO }, /* source */ - { 0x866b18, KEY_MUTE }, /* mute */ - { 0x866b19, KEY_CAMERA }, /* snapshot */ - { 0x866b1a, KEY_SEARCH }, /* scan */ -diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c -index 777a700..bd78d6a 100644 ---- a/drivers/media/rc/keymaps/rc-pixelview-new.c -+++ b/drivers/media/rc/keymaps/rc-pixelview-new.c -@@ -33,7 +33,7 @@ static struct rc_map_table pixelview_new[] = { - { 0x3e, KEY_0 }, - - { 0x1c, KEY_AGAIN }, /* LOOP */ -- { 0x3f, KEY_MEDIA }, /* Source */ -+ { 0x3f, KEY_VIDEO }, /* Source */ - { 0x1f, KEY_LAST }, /* +100 */ - { 0x1b, KEY_MUTE }, - -diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c -index 0ec5988..06187e7 100644 ---- a/drivers/media/rc/keymaps/rc-pixelview.c -+++ b/drivers/media/rc/keymaps/rc-pixelview.c -@@ -15,7 +15,7 @@ - static struct rc_map_table pixelview[] = { - - { 0x1e, KEY_POWER }, /* power */ -- { 0x07, KEY_MEDIA }, /* source */ -+ { 0x07, KEY_VIDEO }, /* source */ - { 0x1c, KEY_SEARCH }, /* scan */ - - -diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c -index 83a418d..5e8beee 100644 ---- a/drivers/media/rc/keymaps/rc-pv951.c -+++ b/drivers/media/rc/keymaps/rc-pv951.c -@@ -46,10 +46,10 @@ static struct rc_map_table pv951[] = { - { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ - - /* Not sure what to do with these ones! */ -- { 0x0f, KEY_SELECT }, /* SOURCE */ -+ { 0x0f, KEY_VIDEO }, /* SOURCE */ - { 0x0a, KEY_KPPLUS }, /* +100 */ - { 0x14, KEY_EQUAL }, /* SYNC */ -- { 0x1c, KEY_MEDIA }, /* PC/TV */ -+ { 0x1c, KEY_TV }, /* PC/TV */ - }; - - static struct rc_map_list pv951_map = { -diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c -deleted file mode 100644 -index dfc9b15..0000000 ---- a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c -+++ /dev/null -@@ -1,141 +0,0 @@ --/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller -- * -- * keymap imported from ir-keymaps.c -- * -- * Copyright (c) 2010 by Mauro Carvalho Chehab -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- */ -- --#include -- --/* -- * Hauppauge:the newer, gray remotes (seems there are multiple -- * slightly different versions), shipped with cx88+ivtv cards. -- * -- * This table contains the complete RC5 code, instead of just the data part -- */ -- --static struct rc_map_table rc5_hauppauge_new[] = { -- /* Keys 0 to 9 */ -- { 0x1e00, KEY_0 }, -- { 0x1e01, KEY_1 }, -- { 0x1e02, KEY_2 }, -- { 0x1e03, KEY_3 }, -- { 0x1e04, KEY_4 }, -- { 0x1e05, KEY_5 }, -- { 0x1e06, KEY_6 }, -- { 0x1e07, KEY_7 }, -- { 0x1e08, KEY_8 }, -- { 0x1e09, KEY_9 }, -- -- { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ -- { 0x1e0b, KEY_RED }, /* red button */ -- { 0x1e0c, KEY_RADIO }, -- { 0x1e0d, KEY_MENU }, -- { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ -- { 0x1e0f, KEY_MUTE }, -- { 0x1e10, KEY_VOLUMEUP }, -- { 0x1e11, KEY_VOLUMEDOWN }, -- { 0x1e12, KEY_PREVIOUS }, /* previous channel */ -- { 0x1e14, KEY_UP }, -- { 0x1e15, KEY_DOWN }, -- { 0x1e16, KEY_LEFT }, -- { 0x1e17, KEY_RIGHT }, -- { 0x1e18, KEY_VIDEO }, /* Videos */ -- { 0x1e19, KEY_AUDIO }, /* Music */ -- /* 0x1e1a: Pictures - presume this means -- "Multimedia Home Platform" - -- no "PICTURES" key in input.h -- */ -- { 0x1e1a, KEY_MHP }, -- -- { 0x1e1b, KEY_EPG }, /* Guide */ -- { 0x1e1c, KEY_TV }, -- { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ -- { 0x1e1f, KEY_EXIT }, /* back/exit */ -- { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ -- { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ -- { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ -- { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ -- { 0x1e25, KEY_ENTER }, /* OK */ -- { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ -- { 0x1e29, KEY_BLUE }, /* blue key */ -- { 0x1e2e, KEY_GREEN }, /* green button */ -- { 0x1e30, KEY_PAUSE }, /* pause */ -- { 0x1e32, KEY_REWIND }, /* backward << */ -- { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ -- { 0x1e35, KEY_PLAY }, -- { 0x1e36, KEY_STOP }, -- { 0x1e37, KEY_RECORD }, /* recording */ -- { 0x1e38, KEY_YELLOW }, /* yellow key */ -- { 0x1e3b, KEY_SELECT }, /* top right button */ -- { 0x1e3c, KEY_ZOOM }, /* full */ -- { 0x1e3d, KEY_POWER }, /* system power (green button) */ -- -- /* Keycodes for DSR-0112 remote bundled with Haupauge MiniStick */ -- { 0x1d00, KEY_0 }, -- { 0x1d01, KEY_1 }, -- { 0x1d02, KEY_2 }, -- { 0x1d03, KEY_3 }, -- { 0x1d04, KEY_4 }, -- { 0x1d05, KEY_5 }, -- { 0x1d06, KEY_6 }, -- { 0x1d07, KEY_7 }, -- { 0x1d08, KEY_8 }, -- { 0x1d09, KEY_9 }, -- { 0x1d0a, KEY_TEXT }, -- { 0x1d0d, KEY_MENU }, -- { 0x1d0f, KEY_MUTE }, -- { 0x1d10, KEY_VOLUMEUP }, -- { 0x1d11, KEY_VOLUMEDOWN }, -- { 0x1d12, KEY_PREVIOUS }, /* Prev.Ch .. ??? */ -- { 0x1d14, KEY_UP }, -- { 0x1d15, KEY_DOWN }, -- { 0x1d16, KEY_LEFT }, -- { 0x1d17, KEY_RIGHT }, -- { 0x1d1c, KEY_TV }, -- { 0x1d1e, KEY_NEXT }, /* >| */ -- { 0x1d1f, KEY_EXIT }, -- { 0x1d20, KEY_CHANNELUP }, -- { 0x1d21, KEY_CHANNELDOWN }, -- { 0x1d24, KEY_LAST }, /* <| */ -- { 0x1d25, KEY_OK }, -- { 0x1d30, KEY_PAUSE }, -- { 0x1d32, KEY_REWIND }, -- { 0x1d34, KEY_FASTFORWARD }, -- { 0x1d35, KEY_PLAY }, -- { 0x1d36, KEY_STOP }, -- { 0x1d37, KEY_RECORD }, -- { 0x1d3b, KEY_GOTO }, -- { 0x1d3d, KEY_POWER }, -- { 0x1d3f, KEY_HOME }, --}; -- --static struct rc_map_list rc5_hauppauge_new_map = { -- .map = { -- .scan = rc5_hauppauge_new, -- .size = ARRAY_SIZE(rc5_hauppauge_new), -- .rc_type = RC_TYPE_RC5, -- .name = RC_MAP_RC5_HAUPPAUGE_NEW, -- } --}; -- --static int __init init_rc_map_rc5_hauppauge_new(void) --{ -- return rc_map_register(&rc5_hauppauge_new_map); --} -- --static void __exit exit_rc_map_rc5_hauppauge_new(void) --{ -- rc_map_unregister(&rc5_hauppauge_new_map); --} -- --module_init(init_rc_map_rc5_hauppauge_new) --module_exit(exit_rc_map_rc5_hauppauge_new) -- --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Mauro Carvalho Chehab "); -diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c -deleted file mode 100644 -index 4fcef9f..0000000 ---- a/drivers/media/rc/keymaps/rc-rc5-tv.c -+++ /dev/null -@@ -1,81 +0,0 @@ --/* rc5-tv.h - Keytable for rc5_tv Remote Controller -- * -- * keymap imported from ir-keymaps.c -- * -- * Copyright (c) 2010 by Mauro Carvalho Chehab -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- */ -- --#include -- --/* generic RC5 keytable */ --/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ --/* used by old (black) Hauppauge remotes */ -- --static struct rc_map_table rc5_tv[] = { -- /* Keys 0 to 9 */ -- { 0x00, KEY_0 }, -- { 0x01, KEY_1 }, -- { 0x02, KEY_2 }, -- { 0x03, KEY_3 }, -- { 0x04, KEY_4 }, -- { 0x05, KEY_5 }, -- { 0x06, KEY_6 }, -- { 0x07, KEY_7 }, -- { 0x08, KEY_8 }, -- { 0x09, KEY_9 }, -- -- { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ -- { 0x0c, KEY_POWER }, /* standby */ -- { 0x0d, KEY_MUTE }, /* mute / demute */ -- { 0x0f, KEY_TV }, /* display */ -- { 0x10, KEY_VOLUMEUP }, -- { 0x11, KEY_VOLUMEDOWN }, -- { 0x12, KEY_BRIGHTNESSUP }, -- { 0x13, KEY_BRIGHTNESSDOWN }, -- { 0x1e, KEY_SEARCH }, /* search + */ -- { 0x20, KEY_CHANNELUP }, /* channel / program + */ -- { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ -- { 0x22, KEY_CHANNEL }, /* alt / channel */ -- { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ -- { 0x26, KEY_SLEEP }, /* sleeptimer */ -- { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ -- { 0x30, KEY_PAUSE }, -- { 0x32, KEY_REWIND }, -- { 0x33, KEY_GOTO }, -- { 0x35, KEY_PLAY }, -- { 0x36, KEY_STOP }, -- { 0x37, KEY_RECORD }, /* recording */ -- { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ -- { 0x3d, KEY_SUSPEND }, /* system standby */ -- --}; -- --static struct rc_map_list rc5_tv_map = { -- .map = { -- .scan = rc5_tv, -- .size = ARRAY_SIZE(rc5_tv), -- .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ -- .name = RC_MAP_RC5_TV, -- } --}; -- --static int __init init_rc_map_rc5_tv(void) --{ -- return rc_map_register(&rc5_tv_map); --} -- --static void __exit exit_rc_map_rc5_tv(void) --{ -- rc_map_unregister(&rc5_tv_map); --} -- --module_init(init_rc_map_rc5_tv) --module_exit(exit_rc_map_rc5_tv) -- --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("Mauro Carvalho Chehab "); -diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c -index 2f5dc06..8dd519e 100644 ---- a/drivers/media/rc/keymaps/rc-rc6-mce.c -+++ b/drivers/media/rc/keymaps/rc-rc6-mce.c -@@ -30,7 +30,7 @@ static struct rc_map_table rc6_mce[] = { - { 0x800f040a, KEY_DELETE }, - { 0x800f040b, KEY_ENTER }, - { 0x800f040c, KEY_POWER }, /* PC Power */ -- { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ -+ { 0x800f040d, KEY_LEFTMETA }, /* Windows MCE button */ - { 0x800f040e, KEY_MUTE }, - { 0x800f040f, KEY_INFO }, - -diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c -index 2d14598..6813d11 100644 ---- a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c -+++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c -@@ -35,7 +35,7 @@ static struct rc_map_table real_audio_220_32_keys[] = { - { 0x15, KEY_CHANNELDOWN}, - { 0x16, KEY_ENTER}, - -- { 0x11, KEY_LIST}, /* Source */ -+ { 0x11, KEY_VIDEO}, /* Source */ - { 0x0d, KEY_AUDIO}, /* stereo */ - - { 0x0f, KEY_PREVIOUS}, /* Prev */ -diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c -index 2747db4..0062ca2 100644 ---- a/drivers/media/rc/keymaps/rc-winfast.c -+++ b/drivers/media/rc/keymaps/rc-winfast.c -@@ -27,15 +27,15 @@ static struct rc_map_table winfast[] = { - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - -- { 0x00, KEY_POWER }, -+ { 0x00, KEY_POWER2 }, - { 0x1b, KEY_AUDIO }, /* Audio Source */ - { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ - { 0x1e, KEY_VIDEO }, /* Video Source */ - { 0x16, KEY_INFO }, /* Display information */ -- { 0x04, KEY_VOLUMEUP }, -- { 0x08, KEY_VOLUMEDOWN }, -- { 0x0c, KEY_CHANNELUP }, -- { 0x10, KEY_CHANNELDOWN }, -+ { 0x04, KEY_LEFT }, -+ { 0x08, KEY_RIGHT }, -+ { 0x0c, KEY_UP }, -+ { 0x10, KEY_DOWN }, - { 0x03, KEY_ZOOM }, /* fullscreen */ - { 0x1f, KEY_TEXT }, /* closed caption/teletext */ - { 0x20, KEY_SLEEP }, -@@ -47,7 +47,7 @@ static struct rc_map_table winfast[] = { - { 0x2e, KEY_BLUE }, - { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ - { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ -- { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ -+ { 0x2a, KEY_TV2 }, /* PIP (Picture in picture */ - { 0x21, KEY_DOT }, - { 0x13, KEY_ENTER }, - { 0x11, KEY_LAST }, /* Recall (last channel */ -@@ -57,7 +57,7 @@ static struct rc_map_table winfast[] = { - { 0x25, KEY_TIME }, /* Time Shifting */ - { 0x26, KEY_STOP }, - { 0x27, KEY_RECORD }, -- { 0x28, KEY_SAVE }, /* Screenshot */ -+ { 0x28, KEY_CAMERA }, /* Screenshot */ - { 0x2f, KEY_MENU }, - { 0x30, KEY_CANCEL }, - { 0x31, KEY_CHANNEL }, /* Channel Surf */ -@@ -70,10 +70,10 @@ static struct rc_map_table winfast[] = { - { 0x38, KEY_DVD }, - - { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ -- { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ -- { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ -- { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ -- { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ -+ { 0x3e, KEY_VOLUMEUP }, /* MCE +VOL, on Y04G0033 */ -+ { 0x3a, KEY_VOLUMEDOWN }, /* MCE -VOL, on Y04G0033 */ -+ { 0x3b, KEY_CHANNELUP }, /* MCE +CH, on Y04G0033 */ -+ { 0x3f, KEY_CHANNELDOWN } /* MCE -CH, on Y04G0033 */ - }; - - static struct rc_map_list winfast_map = { -diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c -index e4f8eac..044fb7a 100644 ---- a/drivers/media/rc/mceusb.c -+++ b/drivers/media/rc/mceusb.c -@@ -186,7 +186,7 @@ static const struct mceusb_model mceusb_model[] = { - * remotes, but we should have something handy, - * to allow testing it - */ -- .rc_map = RC_MAP_RC5_HAUPPAUGE_NEW, -+ .rc_map = RC_MAP_HAUPPAUGE, - .name = "Conexant Hybrid TV (cx231xx) MCE IR", - }, - [CX_HYBRID_TV] = { -@@ -261,7 +261,7 @@ static struct usb_device_id mceusb_dev_table[] = { - .driver_info = MCE_GEN2_TX_INV }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0011), -- .driver_info = MCE_GEN2_TX_INV }, -+ .driver_info = MCE_GEN3 }, - /* Ricavision internal Infrared Transceiver */ - { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, - /* Itron ione Libra Q-11 */ -diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c -index c330fb9..040aaa8 100644 ---- a/drivers/media/video/cx18/cx18-i2c.c -+++ b/drivers/media/video/cx18/cx18-i2c.c -@@ -96,7 +96,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, - /* Our default information for ir-kbd-i2c.c to use */ - switch (hw) { - case CX18_HW_Z8F0811_IR_RX_HAUP: -- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = cx->card_name; -diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c -index 199b996..e97cafd 100644 ---- a/drivers/media/video/cx23885/cx23885-input.c -+++ b/drivers/media/video/cx23885/cx23885-input.c -@@ -264,7 +264,7 @@ int cx23885_input_init(struct cx23885_dev *dev) - driver_type = RC_DRIVER_IR_RAW; - allowed_protos = RC_TYPE_ALL; - /* The grey Hauppauge RC-5 remote */ -- rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; -+ rc_map = RC_MAP_HAUPPAUGE; - break; - case CX23885_BOARD_TEVII_S470: - /* Integrated CX23885 IR controller */ -diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c -index fbfbba5..c820e2f 100644 ---- a/drivers/media/video/cx88/cx88-input.c -+++ b/drivers/media/video/cx88/cx88-input.c -@@ -283,7 +283,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) - case CX88_BOARD_PCHDTV_HD3000: - case CX88_BOARD_PCHDTV_HD5500: - case CX88_BOARD_HAUPPAUGE_IRONLY: -- ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ ir_codes = RC_MAP_HAUPPAUGE; - ir->sampling = 1; - break; - case CX88_BOARD_WINFAST_DTV2000H: -@@ -604,7 +604,7 @@ void cx88_i2c_init_ir(struct cx88_core *core) - if (*addrp == 0x71) { - /* Hauppauge XVR */ - core->init_data.name = "cx88 Hauppauge XVR remote"; -- core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ core->init_data.ir_codes = RC_MAP_HAUPPAUGE; - core->init_data.type = RC_TYPE_RC5; - core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - -diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c -index 87f77a3..69fcea8 100644 ---- a/drivers/media/video/em28xx/em28xx-cards.c -+++ b/drivers/media/video/em28xx/em28xx-cards.c -@@ -834,7 +834,7 @@ struct em28xx_board em28xx_boards[] = { - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, -- .ir_codes = RC_MAP_HAUPPAUGE_NEW, -+ .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, -@@ -859,7 +859,7 @@ struct em28xx_board em28xx_boards[] = { - .tuner_type = TUNER_XC2028, - .tuner_gpio = default_tuner_gpio, - .mts_firmware = 1, -- .ir_codes = RC_MAP_HAUPPAUGE_NEW, -+ .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, -@@ -885,7 +885,7 @@ struct em28xx_board em28xx_boards[] = { - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, -- .ir_codes = RC_MAP_HAUPPAUGE_NEW, -+ .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, -@@ -911,7 +911,7 @@ struct em28xx_board em28xx_boards[] = { - .mts_firmware = 1, - .has_dvb = 1, - .dvb_gpio = hauppauge_wintv_hvr_900_digital, -- .ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW, -+ .ir_codes = RC_MAP_HAUPPAUGE, - .decoder = EM28XX_TVP5150, - .input = { { - .type = EM28XX_VMUX_TELEVISION, -@@ -2430,7 +2430,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev) - dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; - break; - case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: -- dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; -+ dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; - dev->init_data.get_key = em28xx_get_key_em_haup; - dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; - break; -diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c -index e53fa55..2a1ac28 100644 ---- a/drivers/media/video/hdpvr/hdpvr-i2c.c -+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c -@@ -52,25 +52,36 @@ struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev) - }; - - /* Our default information for ir-kbd-i2c.c to use */ -- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = "HD-PVR"; -+ init_data->polling_interval = 405; /* ms, duplicated from Windows */ - hdpvr_ir_rx_i2c_board_info.platform_data = init_data; - - return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info); - } - - static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus, -- unsigned char addr, char *data, int len) -+ unsigned char addr, char *wdata, int wlen, -+ char *data, int len) - { - int ret; - -- if (len > sizeof(dev->i2c_buf)) -+ if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf))) - return -EINVAL; - -- ret = usb_control_msg(dev->udev, -- usb_rcvctrlpipe(dev->udev, 0), -+ if (wlen) { -+ memcpy(&dev->i2c_buf, wdata, wlen); -+ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), -+ REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, -+ (bus << 8) | addr, 0, &dev->i2c_buf, -+ wlen, 1000); -+ if (ret < 0) -+ return ret; -+ } -+ -+ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), - REQTYPE_I2C_READ, CTRL_READ_REQUEST, - (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); - -@@ -92,16 +103,14 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus, - return -EINVAL; - - memcpy(&dev->i2c_buf, data, len); -- ret = usb_control_msg(dev->udev, -- usb_sndctrlpipe(dev->udev, 0), -+ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST, - (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000); - - if (ret < 0) - return ret; - -- ret = usb_control_msg(dev->udev, -- usb_rcvctrlpipe(dev->udev, 0), -+ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), - REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST, - 0, 0, &dev->i2c_buf, 2, 1000); - -@@ -117,24 +126,49 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs, - int num) - { - struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter); -- int retval = 0, i, addr; -+ int retval = 0, addr; - - if (num <= 0) - return 0; - - mutex_lock(&dev->i2c_mutex); - -- for (i = 0; i < num && !retval; i++) { -- addr = msgs[i].addr << 1; -+ addr = msgs[0].addr << 1; - -- if (msgs[i].flags & I2C_M_RD) -- retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf, -- msgs[i].len); -+ if (num == 1) { -+ if (msgs[0].flags & I2C_M_RD) -+ retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0, -+ msgs[0].buf, msgs[0].len); - else -- retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf, -- msgs[i].len); -+ retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf, -+ msgs[0].len); -+ } else if (num == 2) { -+ if (msgs[0].addr != msgs[1].addr) { -+ v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer " -+ "with conflicting target addresses\n"); -+ retval = -EINVAL; -+ goto out; -+ } -+ -+ if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) { -+ v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with " -+ "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD, -+ msgs[1].flags & I2C_M_RD); -+ retval = -EINVAL; -+ goto out; -+ } -+ -+ /* -+ * Write followed by atomic read is the only complex xfer that -+ * we actually support here. -+ */ -+ retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len, -+ msgs[1].buf, msgs[1].len); -+ } else { -+ v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num); - } - -+out: - mutex_unlock(&dev->i2c_mutex); - - return retval ? retval : num; -@@ -158,11 +192,11 @@ static struct i2c_adapter hdpvr_i2c_adapter_template = { - - static int hdpvr_activate_ir(struct hdpvr_device *dev) - { -- char buffer[8]; -+ char buffer[2]; - - mutex_lock(&dev->i2c_mutex); - -- hdpvr_i2c_read(dev, 0, 0x54, buffer, 1); -+ hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1); - - buffer[0] = 0; - buffer[1] = 0x8; -diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c -index a221ad6..3ab875d 100644 ---- a/drivers/media/video/ir-kbd-i2c.c -+++ b/drivers/media/video/ir-kbd-i2c.c -@@ -55,10 +55,6 @@ - static int debug; - module_param(debug, int, 0644); /* debug level (0,1,2) */ - --static int hauppauge; --module_param(hauppauge, int, 0644); /* Choose Hauppauge remote */ --MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)"); -- - - #define MODULE_NAME "ir-kbd-i2c" - #define dprintk(level, fmt, arg...) if (debug >= level) \ -@@ -105,10 +101,6 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, - /* invalid key press */ - return 0; - -- if (dev!=0x1e && dev!=0x1f) -- /* not a hauppauge remote */ -- return 0; -- - if (!range) - code += 64; - -@@ -116,7 +108,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw, - start, range, toggle, dev, code); - - /* return key */ -- *ir_key = code; -+ *ir_key = (dev << 8) | code; - *ir_raw = ircode; - return 1; - } -@@ -312,11 +304,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) - name = "Hauppauge"; - ir->get_key = get_key_haup; - rc_type = RC_TYPE_RC5; -- if (hauppauge == 1) { -- ir_codes = RC_MAP_HAUPPAUGE_NEW; -- } else { -- ir_codes = RC_MAP_RC5_TV; -- } -+ ir_codes = RC_MAP_HAUPPAUGE; - break; - case 0x30: - name = "KNC One"; -@@ -340,7 +328,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) - name = "Hauppauge/Zilog Z8"; - ir->get_key = get_key_haup_xvr; - rc_type = RC_TYPE_RC5; -- ir_codes = hauppauge ? RC_MAP_HAUPPAUGE_NEW : RC_MAP_RC5_TV; -+ ir_codes = RC_MAP_HAUPPAUGE; - break; - } - -diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c -index 9fb86a0..d47f41a 100644 ---- a/drivers/media/video/ivtv/ivtv-i2c.c -+++ b/drivers/media/video/ivtv/ivtv-i2c.c -@@ -205,15 +205,14 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) - break; - case IVTV_HW_I2C_IR_RX_HAUP_EXT: - case IVTV_HW_I2C_IR_RX_HAUP_INT: -- /* Default to old black remote */ -- init_data->ir_codes = RC_MAP_RC5_TV; -+ init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; - init_data->type = RC_TYPE_RC5; - init_data->name = itv->card_name; - break; - case IVTV_HW_Z8F0811_IR_RX_HAUP: - /* Default to grey remote */ -- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = itv->card_name; -diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c -index 451ecd4..e72d510 100644 ---- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c -+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c -@@ -578,7 +578,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) - switch (hdw->ir_scheme_active) { - case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */ - case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */ -- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; - init_data->type = RC_TYPE_RC5; - init_data->name = hdw->hdw_desc->description; -@@ -593,7 +593,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) - break; - case PVR2_IR_SCHEME_ZILOG: /* HVR-1950 style */ - case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */ -- init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = hdw->hdw_desc->description; -diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c -index 790d667..be1c2a2 100644 ---- a/drivers/media/video/saa7134/saa7134-input.c -+++ b/drivers/media/video/saa7134/saa7134-input.c -@@ -893,7 +893,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) - case SAA7134_BOARD_HAUPPAUGE_HVR1110: - dev->init_data.name = "HVR 1110"; - dev->init_data.get_key = get_key_hvr1110; -- dev->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW; -+ dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; - info.addr = 0x71; - break; - case SAA7134_BOARD_BEHOLD_607FM_MK3: -diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig -index cdaff59..526ec0f 100644 ---- a/drivers/staging/lirc/Kconfig -+++ b/drivers/staging/lirc/Kconfig -@@ -32,18 +32,6 @@ config LIRC_IMON - - Current generation iMON devices use the input layer imon driver. - --config LIRC_IT87 -- tristate "ITE IT87XX CIR Port Receiver" -- depends on LIRC && PNP -- help -- Driver for the ITE IT87xx IR Receiver -- --config LIRC_ITE8709 -- tristate "ITE8709 CIR Port Receiver" -- depends on LIRC && PNP -- help -- Driver for the ITE8709 IR Receiver -- - config LIRC_PARALLEL - tristate "Homebrew Parallel Port Receiver" - depends on LIRC && PARPORT -diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile -index 94af218..d76b0fa 100644 ---- a/drivers/staging/lirc/Makefile -+++ b/drivers/staging/lirc/Makefile -@@ -6,8 +6,6 @@ - obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o - obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o - obj-$(CONFIG_LIRC_IMON) += lirc_imon.o --obj-$(CONFIG_LIRC_IT87) += lirc_it87.o --obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o - obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o - obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o - obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o -diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog -index 2d0263f..a97800a 100644 ---- a/drivers/staging/lirc/TODO.lirc_zilog -+++ b/drivers/staging/lirc/TODO.lirc_zilog -@@ -1,34 +1,33 @@ --1. Both ir-kbd-i2c and lirc_zilog provide support for RX events. --The 'tx_only' lirc_zilog module parameter will allow ir-kbd-i2c --and lirc_zilog to coexist in the kernel, if the user requires such a set-up. --However the IR unit will not work well without coordination between the --two modules. A shared mutex, for transceiver access locking, needs to be --supplied by bridge drivers, in struct IR_i2_init_data, to both ir-kbd-i2c --and lirc_zilog, before they will coexist usefully. This should be fixed --before moving out of staging. -- --2. References and locking need careful examination. For cx18 and ivtv PCI --cards, which are not easily "hot unplugged", the imperfect state of reference --counting and locking is acceptable if not correct. For USB connected units --like HD PVR, PVR USB2, HVR-1900, and HVR1950, the likelyhood of an Ooops on --unplug is probably great. Proper reference counting and locking needs to be --implemented before this module is moved out of staging. -- --3. The binding between hdpvr and lirc_zilog is currently disabled, --due to an OOPS reported a few years ago when both the hdpvr and cx18 --drivers were loaded in his system. More details can be seen at: -- http://www.mail-archive.com/linux-media@vger.kernel.org/msg09163.html --More tests need to be done, in order to fix the reported issue. -- --4. In addition to providing a shared mutex for transceiver access --locking, bridge drivers, if able, should provide a chip reset() callback -+1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for -+the chips supported by lirc_zilog. Before moving lirc_zilog out of staging: -+ -+a. ir-kbd-i2c needs a module parameter added to allow the user to tell -+ ir-kbd-i2c to ignore Z8 IR units. -+ -+b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c -+ does. -+ -+ -+2. lirc_zilog module ref-counting need examination. It has not been -+verified that cdev and lirc_dev will take the proper module references on -+lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node -+is open. -+ -+(The good news is ref-counting of lirc_zilog internal structures appears to be -+complete. Testing has shown the cx18 module can be unloaded out from under -+irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse -+effects. The cx18 module could then be reloaded and irw properly began -+receiving button presses again and ir_send worked without error.) -+ -+ -+3. Bridge drivers, if able, should provide a chip reset() callback - to lirc_zilog via struct IR_i2c_init_data. cx18 and ivtv already have routines --to perform Z8 chip resets via GPIO manipulations. This will allow lirc_zilog -+to perform Z8 chip resets via GPIO manipulations. This would allow lirc_zilog - to bring the chip back to normal when it hangs, in the same places the - original lirc_pvr150 driver code does. This is not strictly needed, so it - is not required to move lirc_zilog out of staging. - --5. Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed -+Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed - and installed on Hauppauge products. When working on either module, developers - must consider at least the following bridge drivers which mention an IR Rx unit - at address 0x71 (indicative of a Z8): -diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c -index 235cab0..4039eda 100644 ---- a/drivers/staging/lirc/lirc_imon.c -+++ b/drivers/staging/lirc/lirc_imon.c -@@ -379,7 +379,7 @@ static ssize_t vfd_write(struct file *file, const char *buf, - struct imon_context *context; - const unsigned char vfd_packet6[] = { - 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; -- int *data_buf; -+ int *data_buf = NULL; - - context = file->private_data; - if (!context) { -diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c -deleted file mode 100644 -index 5938616..0000000 ---- a/drivers/staging/lirc/lirc_it87.c -+++ /dev/null -@@ -1,1027 +0,0 @@ --/* -- * LIRC driver for ITE IT8712/IT8705 CIR port -- * -- * Copyright (C) 2001 Hans-Gunter Lutke Uphues -- * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public License as -- * published by the Free Software Foundation; either version 2 of the -- * License, or (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * General Public License for more details. -- -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -- * USA -- * -- * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based -- * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula -- * -- * Attention: Sendmode only tested with debugging logs -- * -- * 2001/02/27 Christoph Bartelmus : -- * reimplemented read function -- * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, -- * based on work of the following member of the Outertrack Digimatrix -- * Forum: Art103 -- * 2009/12/24 James Edwards implemeted support -- * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the -- * chip identifies as 18. -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include --#include -- --#include --#include -- --#include "lirc_it87.h" -- --#ifdef LIRC_IT87_DIGIMATRIX --static int digimatrix = 1; --static int it87_freq = 36; /* kHz */ --static int irq = 9; --#else --static int digimatrix; --static int it87_freq = 38; /* kHz */ --static int irq = IT87_CIR_DEFAULT_IRQ; --#endif -- --static unsigned long it87_bits_in_byte_out; --static unsigned long it87_send_counter; --static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; -- --#define RBUF_LEN 1024 -- --#define LIRC_DRIVER_NAME "lirc_it87" -- --/* timeout for sequences in jiffies (=5/100s) */ --/* must be longer than TIME_CONST */ --#define IT87_TIMEOUT (HZ*5/100) -- --/* module parameters */ --static int debug; --#define dprintk(fmt, args...) \ -- do { \ -- if (debug) \ -- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ -- fmt, ## args); \ -- } while (0) -- --static int io = IT87_CIR_DEFAULT_IOBASE; --/* receiver demodulator default: off */ --static int it87_enable_demodulator; -- --static int timer_enabled; --static DEFINE_SPINLOCK(timer_lock); --static struct timer_list timerlist; --/* time of last signal change detected */ --static struct timeval last_tv = {0, 0}; --/* time of last UART data ready interrupt */ --static struct timeval last_intr_tv = {0, 0}; --static int last_value; -- --static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); -- --static DEFINE_SPINLOCK(hardware_lock); --static DEFINE_SPINLOCK(dev_lock); --static bool device_open; -- --static int rx_buf[RBUF_LEN]; --unsigned int rx_tail, rx_head; -- --static struct pnp_driver it87_pnp_driver; -- --/* SECTION: Prototypes */ -- --/* Communication with user-space */ --static int lirc_open(struct inode *inode, struct file *file); --static int lirc_close(struct inode *inode, struct file *file); --static unsigned int lirc_poll(struct file *file, poll_table *wait); --static ssize_t lirc_read(struct file *file, char *buf, -- size_t count, loff_t *ppos); --static ssize_t lirc_write(struct file *file, const char *buf, -- size_t n, loff_t *pos); --static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); --static void add_read_queue(int flag, unsigned long val); --static int init_chrdev(void); --static void drop_chrdev(void); --/* Hardware */ --static irqreturn_t it87_interrupt(int irq, void *dev_id); --static void send_space(unsigned long len); --static void send_pulse(unsigned long len); --static void init_send(void); --static void terminate_send(unsigned long len); --static int init_hardware(void); --static void drop_hardware(void); --/* Initialisation */ --static int init_port(void); --static void drop_port(void); -- -- --/* SECTION: Communication with user-space */ -- --static int lirc_open(struct inode *inode, struct file *file) --{ -- spin_lock(&dev_lock); -- if (device_open) { -- spin_unlock(&dev_lock); -- return -EBUSY; -- } -- device_open = true; -- spin_unlock(&dev_lock); -- return 0; --} -- -- --static int lirc_close(struct inode *inode, struct file *file) --{ -- spin_lock(&dev_lock); -- device_open = false; -- spin_unlock(&dev_lock); -- return 0; --} -- -- --static unsigned int lirc_poll(struct file *file, poll_table *wait) --{ -- poll_wait(file, &lirc_read_queue, wait); -- if (rx_head != rx_tail) -- return POLLIN | POLLRDNORM; -- return 0; --} -- -- --static ssize_t lirc_read(struct file *file, char *buf, -- size_t count, loff_t *ppos) --{ -- int n = 0; -- int retval = 0; -- -- while (n < count) { -- if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { -- retval = -EAGAIN; -- break; -- } -- retval = wait_event_interruptible(lirc_read_queue, -- rx_head != rx_tail); -- if (retval) -- break; -- -- if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), -- sizeof(int))) { -- retval = -EFAULT; -- break; -- } -- rx_head = (rx_head + 1) & (RBUF_LEN - 1); -- n += sizeof(int); -- } -- if (n) -- return n; -- return retval; --} -- -- --static ssize_t lirc_write(struct file *file, const char *buf, -- size_t n, loff_t *pos) --{ -- int i = 0; -- int *tx_buf; -- -- if (n % sizeof(int)) -- return -EINVAL; -- tx_buf = memdup_user(buf, n); -- if (IS_ERR(tx_buf)) -- return PTR_ERR(tx_buf); -- n /= sizeof(int); -- init_send(); -- while (1) { -- if (i >= n) -- break; -- if (tx_buf[i]) -- send_pulse(tx_buf[i]); -- i++; -- if (i >= n) -- break; -- if (tx_buf[i]) -- send_space(tx_buf[i]); -- i++; -- } -- terminate_send(tx_buf[i - 1]); -- kfree(tx_buf); -- return n; --} -- -- --static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) --{ -- int retval = 0; -- __u32 value = 0; -- unsigned long hw_flags; -- -- if (cmd == LIRC_GET_FEATURES) -- value = LIRC_CAN_SEND_PULSE | -- LIRC_CAN_SET_SEND_CARRIER | -- LIRC_CAN_REC_MODE2; -- else if (cmd == LIRC_GET_SEND_MODE) -- value = LIRC_MODE_PULSE; -- else if (cmd == LIRC_GET_REC_MODE) -- value = LIRC_MODE_MODE2; -- -- switch (cmd) { -- case LIRC_GET_FEATURES: -- case LIRC_GET_SEND_MODE: -- case LIRC_GET_REC_MODE: -- retval = put_user(value, (__u32 *) arg); -- break; -- -- case LIRC_SET_SEND_MODE: -- case LIRC_SET_REC_MODE: -- retval = get_user(value, (__u32 *) arg); -- break; -- -- case LIRC_SET_SEND_CARRIER: -- retval = get_user(value, (__u32 *) arg); -- if (retval) -- return retval; -- value /= 1000; -- if (value > IT87_CIR_FREQ_MAX || -- value < IT87_CIR_FREQ_MIN) -- return -EINVAL; -- -- it87_freq = value; -- -- spin_lock_irqsave(&hardware_lock, hw_flags); -- outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | -- (it87_freq - IT87_CIR_FREQ_MIN) << 3), -- io + IT87_CIR_TCR2); -- spin_unlock_irqrestore(&hardware_lock, hw_flags); -- dprintk("demodulation frequency: %d kHz\n", it87_freq); -- -- break; -- -- default: -- retval = -EINVAL; -- } -- -- if (retval) -- return retval; -- -- if (cmd == LIRC_SET_REC_MODE) { -- if (value != LIRC_MODE_MODE2) -- retval = -ENOSYS; -- } else if (cmd == LIRC_SET_SEND_MODE) { -- if (value != LIRC_MODE_PULSE) -- retval = -ENOSYS; -- } -- return retval; --} -- --static void add_read_queue(int flag, unsigned long val) --{ -- unsigned int new_rx_tail; -- int newval; -- -- dprintk("add flag %d with val %lu\n", flag, val); -- -- newval = val & PULSE_MASK; -- -- /* -- * statistically, pulses are ~TIME_CONST/2 too long. we could -- * maybe make this more exact, but this is good enough -- */ -- if (flag) { -- /* pulse */ -- if (newval > TIME_CONST / 2) -- newval -= TIME_CONST / 2; -- else /* should not ever happen */ -- newval = 1; -- newval |= PULSE_BIT; -- } else -- newval += TIME_CONST / 2; -- new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); -- if (new_rx_tail == rx_head) { -- dprintk("Buffer overrun.\n"); -- return; -- } -- rx_buf[rx_tail] = newval; -- rx_tail = new_rx_tail; -- wake_up_interruptible(&lirc_read_queue); --} -- -- --static const struct file_operations lirc_fops = { -- .owner = THIS_MODULE, -- .read = lirc_read, -- .write = lirc_write, -- .poll = lirc_poll, -- .unlocked_ioctl = lirc_ioctl, --#ifdef CONFIG_COMPAT -- .compat_ioctl = lirc_ioctl, --#endif -- .open = lirc_open, -- .release = lirc_close, -- .llseek = noop_llseek, --}; -- --static int set_use_inc(void *data) --{ -- return 0; --} -- --static void set_use_dec(void *data) --{ --} -- --static struct lirc_driver driver = { -- .name = LIRC_DRIVER_NAME, -- .minor = -1, -- .code_length = 1, -- .sample_rate = 0, -- .data = NULL, -- .add_to_buf = NULL, -- .set_use_inc = set_use_inc, -- .set_use_dec = set_use_dec, -- .fops = &lirc_fops, -- .dev = NULL, -- .owner = THIS_MODULE, --}; -- -- --static int init_chrdev(void) --{ -- driver.minor = lirc_register_driver(&driver); -- -- if (driver.minor < 0) { -- printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); -- return -EIO; -- } -- return 0; --} -- -- --static void drop_chrdev(void) --{ -- lirc_unregister_driver(driver.minor); --} -- -- --/* SECTION: Hardware */ --static long delta(struct timeval *tv1, struct timeval *tv2) --{ -- unsigned long deltv; -- -- deltv = tv2->tv_sec - tv1->tv_sec; -- if (deltv > 15) -- deltv = 0xFFFFFF; -- else -- deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; -- return deltv; --} -- --static void it87_timeout(unsigned long data) --{ -- unsigned long flags; -- -- /* avoid interference with interrupt */ -- spin_lock_irqsave(&timer_lock, flags); -- -- if (digimatrix) { -- /* We have timed out. Disable the RX mechanism. */ -- -- outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | -- IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); -- if (it87_RXEN_mask) -- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, -- io + IT87_CIR_RCR); -- dprintk(" TIMEOUT\n"); -- timer_enabled = 0; -- -- /* fifo clear */ -- outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, -- io+IT87_CIR_TCR1); -- -- } else { -- /* -- * if last received signal was a pulse, but receiving stopped -- * within the 9 bit frame, we need to finish this pulse and -- * simulate a signal change to from pulse to space. Otherwise -- * upper layers will receive two sequences next time. -- */ -- -- if (last_value) { -- unsigned long pulse_end; -- -- /* determine 'virtual' pulse end: */ -- pulse_end = delta(&last_tv, &last_intr_tv); -- dprintk("timeout add %d for %lu usec\n", -- last_value, pulse_end); -- add_read_queue(last_value, pulse_end); -- last_value = 0; -- last_tv = last_intr_tv; -- } -- } -- spin_unlock_irqrestore(&timer_lock, flags); --} -- --static irqreturn_t it87_interrupt(int irq, void *dev_id) --{ -- unsigned char data; -- struct timeval curr_tv; -- static unsigned long deltv; -- unsigned long deltintrtv; -- unsigned long flags, hw_flags; -- int iir, lsr; -- int fifo = 0; -- static char lastbit; -- char bit; -- -- /* Bit duration in microseconds */ -- const unsigned long bit_duration = 1000000ul / -- (115200 / IT87_CIR_BAUDRATE_DIVISOR); -- -- -- iir = inb(io + IT87_CIR_IIR); -- -- switch (iir & IT87_CIR_IIR_IID) { -- case 0x4: -- case 0x6: -- lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | -- IT87_CIR_RSR_RXFBC); -- fifo = lsr & IT87_CIR_RSR_RXFBC; -- dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); -- -- /* avoid interference with timer */ -- spin_lock_irqsave(&timer_lock, flags); -- spin_lock_irqsave(&hardware_lock, hw_flags); -- if (digimatrix) { -- static unsigned long acc_pulse; -- static unsigned long acc_space; -- -- do { -- data = inb(io + IT87_CIR_DR); -- data = ~data; -- fifo--; -- if (data != 0x00) { -- if (timer_enabled) -- del_timer(&timerlist); -- /* -- * start timer for end of -- * sequence detection -- */ -- timerlist.expires = jiffies + -- IT87_TIMEOUT; -- add_timer(&timerlist); -- timer_enabled = 1; -- } -- /* Loop through */ -- for (bit = 0; bit < 8; ++bit) { -- if ((data >> bit) & 1) { -- ++acc_pulse; -- if (lastbit == 0) { -- add_read_queue(0, -- acc_space * -- bit_duration); -- acc_space = 0; -- } -- } else { -- ++acc_space; -- if (lastbit == 1) { -- add_read_queue(1, -- acc_pulse * -- bit_duration); -- acc_pulse = 0; -- } -- } -- lastbit = (data >> bit) & 1; -- } -- -- } while (fifo != 0); -- } else { /* Normal Operation */ -- do { -- del_timer(&timerlist); -- data = inb(io + IT87_CIR_DR); -- -- dprintk("data=%02x\n", data); -- do_gettimeofday(&curr_tv); -- deltv = delta(&last_tv, &curr_tv); -- deltintrtv = delta(&last_intr_tv, &curr_tv); -- -- dprintk("t %lu , d %d\n", -- deltintrtv, (int)data); -- -- /* -- * if nothing came in last 2 cycles, -- * it was gap -- */ -- if (deltintrtv > TIME_CONST * 2) { -- if (last_value) { -- dprintk("GAP\n"); -- -- /* simulate signal change */ -- add_read_queue(last_value, -- deltv - -- deltintrtv); -- last_value = 0; -- last_tv.tv_sec = -- last_intr_tv.tv_sec; -- last_tv.tv_usec = -- last_intr_tv.tv_usec; -- deltv = deltintrtv; -- } -- } -- data = 1; -- if (data ^ last_value) { -- /* -- * deltintrtv > 2*TIME_CONST, -- * remember ? the other case is -- * timeout -- */ -- add_read_queue(last_value, -- deltv-TIME_CONST); -- last_value = data; -- last_tv = curr_tv; -- if (last_tv.tv_usec >= TIME_CONST) -- last_tv.tv_usec -= TIME_CONST; -- else { -- last_tv.tv_sec--; -- last_tv.tv_usec += 1000000 - -- TIME_CONST; -- } -- } -- last_intr_tv = curr_tv; -- if (data) { -- /* -- * start timer for end of -- * sequence detection -- */ -- timerlist.expires = -- jiffies + IT87_TIMEOUT; -- add_timer(&timerlist); -- } -- outb((inb(io + IT87_CIR_RCR) & -- ~IT87_CIR_RCR_RXEN) | -- IT87_CIR_RCR_RXACT, -- io + IT87_CIR_RCR); -- if (it87_RXEN_mask) -- outb(inb(io + IT87_CIR_RCR) | -- IT87_CIR_RCR_RXEN, -- io + IT87_CIR_RCR); -- fifo--; -- } while (fifo != 0); -- } -- spin_unlock_irqrestore(&hardware_lock, hw_flags); -- spin_unlock_irqrestore(&timer_lock, flags); -- -- return IRQ_RETVAL(IRQ_HANDLED); -- -- default: -- /* not our irq */ -- dprintk("unknown IRQ (shouldn't happen) !!\n"); -- return IRQ_RETVAL(IRQ_NONE); -- } --} -- -- --static void send_it87(unsigned long len, unsigned long stime, -- unsigned char send_byte, unsigned int count_bits) --{ -- long count = len / stime; -- long time_left = 0; -- static unsigned char byte_out; -- unsigned long hw_flags; -- -- dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte); -- -- time_left = (long)len - (long)count * (long)stime; -- count += ((2 * time_left) / stime); -- while (count) { -- long i = 0; -- for (i = 0; i < count_bits; i++) { -- byte_out = (byte_out << 1) | (send_byte & 1); -- it87_bits_in_byte_out++; -- } -- if (it87_bits_in_byte_out == 8) { -- dprintk("out=0x%x, tsr_txfbc: 0x%x\n", -- byte_out, -- inb(io + IT87_CIR_TSR) & -- IT87_CIR_TSR_TXFBC); -- -- while ((inb(io + IT87_CIR_TSR) & -- IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) -- ; -- -- spin_lock_irqsave(&hardware_lock, hw_flags); -- outb(byte_out, io + IT87_CIR_DR); -- spin_unlock_irqrestore(&hardware_lock, hw_flags); -- -- it87_bits_in_byte_out = 0; -- it87_send_counter++; -- byte_out = 0; -- } -- count--; -- } --} -- -- --/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */ -- --static void send_space(unsigned long len) --{ -- send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); --} -- --static void send_pulse(unsigned long len) --{ -- send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); --} -- -- --static void init_send() --{ -- unsigned long flags; -- -- spin_lock_irqsave(&hardware_lock, flags); -- /* RXEN=0: receiver disable */ -- it87_RXEN_mask = 0; -- outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, -- io + IT87_CIR_RCR); -- spin_unlock_irqrestore(&hardware_lock, flags); -- it87_bits_in_byte_out = 0; -- it87_send_counter = 0; --} -- -- --static void terminate_send(unsigned long len) --{ -- unsigned long flags; -- unsigned long last = 0; -- -- last = it87_send_counter; -- /* make sure all necessary data has been sent */ -- while (last == it87_send_counter) -- send_space(len); -- /* wait until all data sent */ -- while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0) -- ; -- /* then re-enable receiver */ -- spin_lock_irqsave(&hardware_lock, flags); -- it87_RXEN_mask = IT87_CIR_RCR_RXEN; -- outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, -- io + IT87_CIR_RCR); -- spin_unlock_irqrestore(&hardware_lock, flags); --} -- -- --static int init_hardware(void) --{ -- unsigned long flags; -- unsigned char it87_rcr = 0; -- -- spin_lock_irqsave(&hardware_lock, flags); -- /* init cir-port */ -- /* enable r/w-access to Baudrate-Register */ -- outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); -- outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); -- outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); -- /* Baudrate Register off, define IRQs: Input only */ -- if (digimatrix) { -- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); -- /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ -- } else { -- outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); -- /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ -- } -- it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; -- if (it87_enable_demodulator) -- it87_rcr |= IT87_CIR_RCR_RXEND; -- outb(it87_rcr, io + IT87_CIR_RCR); -- if (digimatrix) { -- /* Set FIFO depth to 1 byte, and disable TX */ -- outb(inb(io + IT87_CIR_TCR1) | 0x00, -- io + IT87_CIR_TCR1); -- -- /* -- * TX: it87_freq (36kHz), 'reserved' sensitivity -- * setting (0x00) -- */ -- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, -- io + IT87_CIR_TCR2); -- } else { -- /* TX: 38kHz, 13,3us (pulse-width) */ -- outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, -- io + IT87_CIR_TCR2); -- } -- spin_unlock_irqrestore(&hardware_lock, flags); -- return 0; --} -- -- --static void drop_hardware(void) --{ -- unsigned long flags; -- -- spin_lock_irqsave(&hardware_lock, flags); -- disable_irq(irq); -- /* receiver disable */ -- it87_RXEN_mask = 0; -- outb(0x1, io + IT87_CIR_RCR); -- /* turn off irqs */ -- outb(0, io + IT87_CIR_IER); -- /* fifo clear */ -- outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); -- /* reset */ -- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); -- enable_irq(irq); -- spin_unlock_irqrestore(&hardware_lock, flags); --} -- -- --static unsigned char it87_read(unsigned char port) --{ -- outb(port, IT87_ADRPORT); -- return inb(IT87_DATAPORT); --} -- -- --static void it87_write(unsigned char port, unsigned char data) --{ -- outb(port, IT87_ADRPORT); -- outb(data, IT87_DATAPORT); --} -- -- --/* SECTION: Initialisation */ -- --static int init_port(void) --{ -- unsigned long hw_flags; -- int retval = 0; -- -- unsigned char init_bytes[4] = IT87_INIT; -- unsigned char it87_chipid = 0; -- unsigned char ldn = 0; -- unsigned int it87_io = 0; -- unsigned int it87_irq = 0; -- -- /* Enter MB PnP Mode */ -- outb(init_bytes[0], IT87_ADRPORT); -- outb(init_bytes[1], IT87_ADRPORT); -- outb(init_bytes[2], IT87_ADRPORT); -- outb(init_bytes[3], IT87_ADRPORT); -- -- /* 8712 or 8705 ? */ -- it87_chipid = it87_read(IT87_CHIP_ID1); -- if (it87_chipid != 0x87) { -- retval = -ENXIO; -- return retval; -- } -- it87_chipid = it87_read(IT87_CHIP_ID2); -- if ((it87_chipid != 0x05) && -- (it87_chipid != 0x12) && -- (it87_chipid != 0x18) && -- (it87_chipid != 0x20)) { -- printk(KERN_INFO LIRC_DRIVER_NAME -- ": no IT8704/05/12/18/20 found (claimed IT87%02x), " -- "exiting..\n", it87_chipid); -- retval = -ENXIO; -- return retval; -- } -- printk(KERN_INFO LIRC_DRIVER_NAME -- ": found IT87%02x.\n", -- it87_chipid); -- -- /* get I/O-Port and IRQ */ -- if (it87_chipid == 0x12 || it87_chipid == 0x18) -- ldn = IT8712_CIR_LDN; -- else -- ldn = IT8705_CIR_LDN; -- it87_write(IT87_LDN, ldn); -- -- it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + -- it87_read(IT87_CIR_BASE_LSB); -- if (it87_io == 0) { -- if (io == 0) -- io = IT87_CIR_DEFAULT_IOBASE; -- printk(KERN_INFO LIRC_DRIVER_NAME -- ": set default io 0x%x\n", -- io); -- it87_write(IT87_CIR_BASE_MSB, io / 0x100); -- it87_write(IT87_CIR_BASE_LSB, io % 0x100); -- } else -- io = it87_io; -- -- it87_irq = it87_read(IT87_CIR_IRQ); -- if (digimatrix || it87_irq == 0) { -- if (irq == 0) -- irq = IT87_CIR_DEFAULT_IRQ; -- printk(KERN_INFO LIRC_DRIVER_NAME -- ": set default irq 0x%x\n", -- irq); -- it87_write(IT87_CIR_IRQ, irq); -- } else -- irq = it87_irq; -- -- spin_lock_irqsave(&hardware_lock, hw_flags); -- /* reset */ -- outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); -- /* fifo clear */ -- outb(IT87_CIR_TCR1_FIFOCLR | -- /* IT87_CIR_TCR1_ILE | */ -- IT87_CIR_TCR1_TXRLE | -- IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); -- spin_unlock_irqrestore(&hardware_lock, hw_flags); -- -- /* get I/O port access and IRQ line */ -- if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { -- printk(KERN_ERR LIRC_DRIVER_NAME -- ": i/o port 0x%.4x already in use.\n", io); -- /* Leaving MB PnP Mode */ -- it87_write(IT87_CFGCTRL, 0x2); -- return -EBUSY; -- } -- -- /* activate CIR-Device */ -- it87_write(IT87_CIR_ACT, 0x1); -- -- /* Leaving MB PnP Mode */ -- it87_write(IT87_CFGCTRL, 0x2); -- -- retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, -- LIRC_DRIVER_NAME, NULL); -- if (retval < 0) { -- printk(KERN_ERR LIRC_DRIVER_NAME -- ": IRQ %d already in use.\n", -- irq); -- release_region(io, 8); -- return retval; -- } -- -- printk(KERN_INFO LIRC_DRIVER_NAME -- ": I/O port 0x%.4x, IRQ %d.\n", io, irq); -- -- init_timer(&timerlist); -- timerlist.function = it87_timeout; -- timerlist.data = 0xabadcafe; -- -- return 0; --} -- -- --static void drop_port(void) --{ --#if 0 -- unsigned char init_bytes[4] = IT87_INIT; -- -- /* Enter MB PnP Mode */ -- outb(init_bytes[0], IT87_ADRPORT); -- outb(init_bytes[1], IT87_ADRPORT); -- outb(init_bytes[2], IT87_ADRPORT); -- outb(init_bytes[3], IT87_ADRPORT); -- -- /* deactivate CIR-Device */ -- it87_write(IT87_CIR_ACT, 0x0); -- -- /* Leaving MB PnP Mode */ -- it87_write(IT87_CFGCTRL, 0x2); --#endif -- -- del_timer_sync(&timerlist); -- free_irq(irq, NULL); -- release_region(io, 8); --} -- -- --static int init_lirc_it87(void) --{ -- int retval; -- -- init_waitqueue_head(&lirc_read_queue); -- retval = init_port(); -- if (retval < 0) -- return retval; -- init_hardware(); -- printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); -- return 0; --} -- --static int it87_probe(struct pnp_dev *pnp_dev, -- const struct pnp_device_id *dev_id) --{ -- int retval; -- -- driver.dev = &pnp_dev->dev; -- -- retval = init_chrdev(); -- if (retval < 0) -- return retval; -- -- retval = init_lirc_it87(); -- if (retval) -- goto init_lirc_it87_failed; -- -- return 0; -- --init_lirc_it87_failed: -- drop_chrdev(); -- -- return retval; --} -- --static int __init lirc_it87_init(void) --{ -- return pnp_register_driver(&it87_pnp_driver); --} -- -- --static void __exit lirc_it87_exit(void) --{ -- drop_hardware(); -- drop_chrdev(); -- drop_port(); -- pnp_unregister_driver(&it87_pnp_driver); -- printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); --} -- --/* SECTION: PNP for ITE8704/13/18 */ -- --static const struct pnp_device_id pnp_dev_table[] = { -- {"ITE8704", 0}, -- {"ITE8713", 0}, -- {} --}; -- --MODULE_DEVICE_TABLE(pnp, pnp_dev_table); -- --static struct pnp_driver it87_pnp_driver = { -- .name = LIRC_DRIVER_NAME, -- .id_table = pnp_dev_table, -- .probe = it87_probe, --}; -- --module_init(lirc_it87_init); --module_exit(lirc_it87_exit); -- --MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port"); --MODULE_AUTHOR("Hans-Gunter Lutke Uphues"); --MODULE_LICENSE("GPL"); -- --module_param(io, int, S_IRUGO); --MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); -- --module_param(irq, int, S_IRUGO); --#ifdef LIRC_IT87_DIGIMATRIX --MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); --#else --MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); --#endif -- --module_param(it87_enable_demodulator, bool, S_IRUGO); --MODULE_PARM_DESC(it87_enable_demodulator, -- "Receiver demodulator enable/disable (1/0), default: 0"); -- --module_param(debug, bool, S_IRUGO | S_IWUSR); --MODULE_PARM_DESC(debug, "Enable debugging messages"); -- --module_param(digimatrix, bool, S_IRUGO | S_IWUSR); --#ifdef LIRC_IT87_DIGIMATRIX --MODULE_PARM_DESC(digimatrix, -- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); --#else --MODULE_PARM_DESC(digimatrix, -- "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); --#endif -- -- --module_param(it87_freq, int, S_IRUGO); --#ifdef LIRC_IT87_DIGIMATRIX --MODULE_PARM_DESC(it87_freq, -- "Carrier demodulator frequency (kHz), (default: 36)"); --#else --MODULE_PARM_DESC(it87_freq, -- "Carrier demodulator frequency (kHz), (default: 38)"); --#endif -diff --git a/drivers/staging/lirc/lirc_it87.h b/drivers/staging/lirc/lirc_it87.h -deleted file mode 100644 -index cf021c8..0000000 ---- a/drivers/staging/lirc/lirc_it87.h -+++ /dev/null -@@ -1,116 +0,0 @@ --/* lirc_it87.h */ --/* SECTION: Definitions */ -- --/********************************* ITE IT87xx ************************/ -- --/* based on the following documentation from ITE: -- a) IT8712F Preliminary CIR Programming Guide V0.1 -- b) IT8705F Simple LPC I/O Preliminary Specification V0.3 -- c) IT8712F EC-LPC I/O Preliminary Specification V0.5 --*/ -- --/* IT8712/05 Ports: */ --#define IT87_ADRPORT 0x2e --#define IT87_DATAPORT 0x2f --#define IT87_INIT {0x87, 0x01, 0x55, 0x55} -- --/* alternate Ports: */ --/* --#define IT87_ADRPORT 0x4e --#define IT87_DATAPORT 0x4f --#define IT87_INIT {0x87, 0x01, 0x55, 0xaa} -- */ -- --/* IT8712/05 Registers */ --#define IT87_CFGCTRL 0x2 --#define IT87_LDN 0x7 --#define IT87_CHIP_ID1 0x20 --#define IT87_CHIP_ID2 0x21 --#define IT87_CFG_VERSION 0x22 --#define IT87_SWSUSPEND 0x23 -- --#define IT8712_CIR_LDN 0xa --#define IT8705_CIR_LDN 0x7 -- --/* CIR Configuration Registers: */ --#define IT87_CIR_ACT 0x30 --#define IT87_CIR_BASE_MSB 0x60 --#define IT87_CIR_BASE_LSB 0x61 --#define IT87_CIR_IRQ 0x70 --#define IT87_CIR_CONFIG 0xf0 -- --/* List of IT87_CIR registers: offset to BaseAddr */ --#define IT87_CIR_DR 0 --#define IT87_CIR_IER 1 --#define IT87_CIR_RCR 2 --#define IT87_CIR_TCR1 3 --#define IT87_CIR_TCR2 4 --#define IT87_CIR_TSR 5 --#define IT87_CIR_RSR 6 --#define IT87_CIR_BDLR 5 --#define IT87_CIR_BDHR 6 --#define IT87_CIR_IIR 7 -- --/* Bit Definition */ --/* IER: */ --#define IT87_CIR_IER_TM_EN 0x80 --#define IT87_CIR_IER_RESEVED 0x40 --#define IT87_CIR_IER_RESET 0x20 --#define IT87_CIR_IER_BR 0x10 --#define IT87_CIR_IER_IEC 0x8 --#define IT87_CIR_IER_RFOIE 0x4 --#define IT87_CIR_IER_RDAIE 0x2 --#define IT87_CIR_IER_TLDLIE 0x1 -- --/* RCR: */ --#define IT87_CIR_RCR_RDWOS 0x80 --#define IT87_CIR_RCR_HCFS 0x40 --#define IT87_CIR_RCR_RXEN 0x20 --#define IT87_CIR_RCR_RXEND 0x10 --#define IT87_CIR_RCR_RXACT 0x8 --#define IT87_CIR_RCR_RXDCR 0x7 -- --/* TCR1: */ --#define IT87_CIR_TCR1_FIFOCLR 0x80 --#define IT87_CIR_TCR1_ILE 0x40 --#define IT87_CIR_TCR1_FIFOTL 0x30 --#define IT87_CIR_TCR1_TXRLE 0x8 --#define IT87_CIR_TCR1_TXENDF 0x4 --#define IT87_CIR_TCR1_TXMPM 0x3 -- --/* TCR2: */ --#define IT87_CIR_TCR2_CFQ 0xf8 --#define IT87_CIR_TCR2_TXMPW 0x7 -- --/* TSR: */ --#define IT87_CIR_TSR_RESERVED 0xc0 --#define IT87_CIR_TSR_TXFBC 0x3f -- --/* RSR: */ --#define IT87_CIR_RSR_RXFTO 0x80 --#define IT87_CIR_RSR_RESERVED 0x40 --#define IT87_CIR_RSR_RXFBC 0x3f -- --/* IIR: */ --#define IT87_CIR_IIR_RESERVED 0xf8 --#define IT87_CIR_IIR_IID 0x6 --#define IT87_CIR_IIR_IIP 0x1 -- --/* TM: */ --#define IT87_CIR_TM_IL_SEL 0x80 --#define IT87_CIR_TM_RESERVED 0x40 --#define IT87_CIR_TM_TM_REG 0x3f -- --#define IT87_CIR_FIFO_SIZE 32 -- --/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ --#define IT87_CIR_BAUDRATE_DIVISOR 0x1 --#define IT87_CIR_DEFAULT_IOBASE 0x310 --#define IT87_CIR_DEFAULT_IRQ 0x7 --#define IT87_CIR_SPACE 0x00 --#define IT87_CIR_PULSE 0xff --#define IT87_CIR_FREQ_MIN 27 --#define IT87_CIR_FREQ_MAX 58 --#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) -- --/********************************* ITE IT87xx ************************/ -diff --git a/drivers/staging/lirc/lirc_ite8709.c b/drivers/staging/lirc/lirc_ite8709.c -deleted file mode 100644 -index cb20cfd..0000000 ---- a/drivers/staging/lirc/lirc_ite8709.c -+++ /dev/null -@@ -1,542 +0,0 @@ --/* -- * LIRC driver for ITE8709 CIR port -- * -- * Copyright (C) 2008 Grégory Lardière -- * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public License as -- * published by the Free Software Foundation; either version 2 of the -- * License, or (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, but -- * WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- * General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -- * USA -- */ -- --#include --#include --#include --#include --#include --#include -- --#include --#include -- --#define LIRC_DRIVER_NAME "lirc_ite8709" -- --#define BUF_CHUNK_SIZE sizeof(int) --#define BUF_SIZE (128*BUF_CHUNK_SIZE) -- --/* -- * The ITE8709 device seems to be the combination of IT8512 superIO chip and -- * a specific firmware running on the IT8512's embedded micro-controller. -- * In addition of the embedded micro-controller, the IT8512 chip contains a -- * CIR module and several other modules. A few modules are directly accessible -- * by the host CPU, but most of them are only accessible by the -- * micro-controller. The CIR module is only accessible by the micro-controller. -- * The battery-backed SRAM module is accessible by the host CPU and the -- * micro-controller. So one of the MC's firmware role is to act as a bridge -- * between the host CPU and the CIR module. The firmware implements a kind of -- * communication protocol using the SRAM module as a shared memory. The IT8512 -- * specification is publicly available on ITE's web site, but the communication -- * protocol is not, so it was reverse-engineered. -- */ -- --/* ITE8709 Registers addresses and values (reverse-engineered) */ --#define ITE8709_MODE 0x1a --#define ITE8709_REG_ADR 0x1b --#define ITE8709_REG_VAL 0x1c --#define ITE8709_IIR 0x1e /* Interrupt identification register */ --#define ITE8709_RFSR 0x1f /* Receiver FIFO status register */ --#define ITE8709_FIFO_START 0x20 -- --#define ITE8709_MODE_READY 0X00 --#define ITE8709_MODE_WRITE 0X01 --#define ITE8709_MODE_READ 0X02 --#define ITE8709_IIR_RDAI 0x02 /* Receiver data available interrupt */ --#define ITE8709_IIR_RFOI 0x04 /* Receiver FIFO overrun interrupt */ --#define ITE8709_RFSR_MASK 0x3f /* FIFO byte count mask */ -- --/* -- * IT8512 CIR-module registers addresses and values -- * (from IT8512 E/F specification v0.4.1) -- */ --#define IT8512_REG_MSTCR 0x01 /* Master control register */ --#define IT8512_REG_IER 0x02 /* Interrupt enable register */ --#define IT8512_REG_CFR 0x04 /* Carrier frequency register */ --#define IT8512_REG_RCR 0x05 /* Receive control register */ --#define IT8512_REG_BDLR 0x08 /* Baud rate divisor low byte register */ --#define IT8512_REG_BDHR 0x09 /* Baud rate divisor high byte register */ -- --#define IT8512_MSTCR_RESET 0x01 /* Reset registers to default value */ --#define IT8512_MSTCR_FIFOCLR 0x02 /* Clear FIFO */ --#define IT8512_MSTCR_FIFOTL_7 0x04 /* FIFO threshold level : 7 */ --#define IT8512_MSTCR_FIFOTL_25 0x0c /* FIFO threshold level : 25 */ --#define IT8512_IER_RDAIE 0x02 /* Enable data interrupt request */ --#define IT8512_IER_RFOIE 0x04 /* Enable FIFO overrun interrupt req */ --#define IT8512_IER_IEC 0x80 /* Enable interrupt request */ --#define IT8512_CFR_CF_36KHZ 0x09 /* Carrier freq : low speed, 36kHz */ --#define IT8512_RCR_RXDCR_1 0x01 /* Demodulation carrier range : 1 */ --#define IT8512_RCR_RXACT 0x08 /* Receiver active */ --#define IT8512_RCR_RXEN 0x80 /* Receiver enable */ --#define IT8512_BDR_6 6 /* Baud rate divisor : 6 */ -- --/* Actual values used by this driver */ --#define CFG_FIFOTL IT8512_MSTCR_FIFOTL_25 --#define CFG_CR_FREQ IT8512_CFR_CF_36KHZ --#define CFG_DCR IT8512_RCR_RXDCR_1 --#define CFG_BDR IT8512_BDR_6 --#define CFG_TIMEOUT 100000 /* Rearm interrupt when a space is > 100 ms */ -- --static int debug; -- --struct ite8709_device { -- int use_count; -- int io; -- int irq; -- spinlock_t hardware_lock; -- __u64 acc_pulse; -- __u64 acc_space; -- char lastbit; -- struct timeval last_tv; -- struct lirc_driver driver; -- struct tasklet_struct tasklet; -- char force_rearm; -- char rearmed; -- char device_busy; --}; -- --#define dprintk(fmt, args...) \ -- do { \ -- if (debug) \ -- printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ -- fmt, ## args); \ -- } while (0) -- -- --static unsigned char ite8709_read(struct ite8709_device *dev, -- unsigned char port) --{ -- outb(port, dev->io); -- return inb(dev->io+1); --} -- --static void ite8709_write(struct ite8709_device *dev, unsigned char port, -- unsigned char data) --{ -- outb(port, dev->io); -- outb(data, dev->io+1); --} -- --static void ite8709_wait_device(struct ite8709_device *dev) --{ -- int i = 0; -- /* -- * loop until device tells it's ready to continue -- * iterations count is usually ~750 but can sometimes achieve 13000 -- */ -- for (i = 0; i < 15000; i++) { -- udelay(2); -- if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY) -- break; -- } --} -- --static void ite8709_write_register(struct ite8709_device *dev, -- unsigned char reg_adr, unsigned char reg_value) --{ -- ite8709_wait_device(dev); -- -- ite8709_write(dev, ITE8709_REG_VAL, reg_value); -- ite8709_write(dev, ITE8709_REG_ADR, reg_adr); -- ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE); --} -- --static void ite8709_init_hardware(struct ite8709_device *dev) --{ -- spin_lock_irq(&dev->hardware_lock); -- dev->device_busy = 1; -- spin_unlock_irq(&dev->hardware_lock); -- -- ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff); -- ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff); -- ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ); -- ite8709_write_register(dev, IT8512_REG_IER, -- IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE); -- ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR); -- ite8709_write_register(dev, IT8512_REG_MSTCR, -- CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); -- ite8709_write_register(dev, IT8512_REG_RCR, -- IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); -- -- spin_lock_irq(&dev->hardware_lock); -- dev->device_busy = 0; -- spin_unlock_irq(&dev->hardware_lock); -- -- tasklet_enable(&dev->tasklet); --} -- --static void ite8709_drop_hardware(struct ite8709_device *dev) --{ -- tasklet_disable(&dev->tasklet); -- -- spin_lock_irq(&dev->hardware_lock); -- dev->device_busy = 1; -- spin_unlock_irq(&dev->hardware_lock); -- -- ite8709_write_register(dev, IT8512_REG_RCR, 0); -- ite8709_write_register(dev, IT8512_REG_MSTCR, -- IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR); -- -- spin_lock_irq(&dev->hardware_lock); -- dev->device_busy = 0; -- spin_unlock_irq(&dev->hardware_lock); --} -- --static int ite8709_set_use_inc(void *data) --{ -- struct ite8709_device *dev; -- dev = data; -- if (dev->use_count == 0) -- ite8709_init_hardware(dev); -- dev->use_count++; -- return 0; --} -- --static void ite8709_set_use_dec(void *data) --{ -- struct ite8709_device *dev; -- dev = data; -- dev->use_count--; -- if (dev->use_count == 0) -- ite8709_drop_hardware(dev); --} -- --static void ite8709_add_read_queue(struct ite8709_device *dev, int flag, -- __u64 val) --{ -- int value; -- -- dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space"); -- -- value = (val > PULSE_MASK) ? PULSE_MASK : val; -- if (flag) -- value |= PULSE_BIT; -- -- if (!lirc_buffer_full(dev->driver.rbuf)) { -- lirc_buffer_write(dev->driver.rbuf, (void *) &value); -- wake_up(&dev->driver.rbuf->wait_poll); -- } --} -- --static irqreturn_t ite8709_interrupt(int irq, void *dev_id) --{ -- unsigned char data; -- int iir, rfsr, i; -- int fifo = 0; -- char bit; -- struct timeval curr_tv; -- -- /* Bit duration in microseconds */ -- const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR); -- -- struct ite8709_device *dev; -- dev = dev_id; -- -- /* -- * If device is busy, we simply discard data because we are in one of -- * these two cases : shutting down or rearming the device, so this -- * doesn't really matter and this avoids waiting too long in IRQ ctx -- */ -- spin_lock(&dev->hardware_lock); -- if (dev->device_busy) { -- spin_unlock(&dev->hardware_lock); -- return IRQ_RETVAL(IRQ_HANDLED); -- } -- -- iir = ite8709_read(dev, ITE8709_IIR); -- -- switch (iir) { -- case ITE8709_IIR_RFOI: -- dprintk("fifo overrun, scheduling forced rearm just in case\n"); -- dev->force_rearm = 1; -- tasklet_schedule(&dev->tasklet); -- spin_unlock(&dev->hardware_lock); -- return IRQ_RETVAL(IRQ_HANDLED); -- -- case ITE8709_IIR_RDAI: -- rfsr = ite8709_read(dev, ITE8709_RFSR); -- fifo = rfsr & ITE8709_RFSR_MASK; -- if (fifo > 32) -- fifo = 32; -- dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo); -- -- if (dev->rearmed) { -- do_gettimeofday(&curr_tv); -- dev->acc_space += 1000000ull -- * (curr_tv.tv_sec - dev->last_tv.tv_sec) -- + (curr_tv.tv_usec - dev->last_tv.tv_usec); -- dev->rearmed = 0; -- } -- for (i = 0; i < fifo; i++) { -- data = ite8709_read(dev, i+ITE8709_FIFO_START); -- data = ~data; -- /* Loop through */ -- for (bit = 0; bit < 8; ++bit) { -- if ((data >> bit) & 1) { -- dev->acc_pulse += bit_duration; -- if (dev->lastbit == 0) { -- ite8709_add_read_queue(dev, 0, -- dev->acc_space); -- dev->acc_space = 0; -- } -- } else { -- dev->acc_space += bit_duration; -- if (dev->lastbit == 1) { -- ite8709_add_read_queue(dev, 1, -- dev->acc_pulse); -- dev->acc_pulse = 0; -- } -- } -- dev->lastbit = (data >> bit) & 1; -- } -- } -- ite8709_write(dev, ITE8709_RFSR, 0); -- -- if (dev->acc_space > CFG_TIMEOUT) { -- dprintk("scheduling rearm IRQ\n"); -- do_gettimeofday(&dev->last_tv); -- dev->force_rearm = 0; -- tasklet_schedule(&dev->tasklet); -- } -- -- spin_unlock(&dev->hardware_lock); -- return IRQ_RETVAL(IRQ_HANDLED); -- -- default: -- /* not our irq */ -- dprintk("unknown IRQ (shouldn't happen) !!\n"); -- spin_unlock(&dev->hardware_lock); -- return IRQ_RETVAL(IRQ_NONE); -- } --} -- --static void ite8709_rearm_irq(unsigned long data) --{ -- struct ite8709_device *dev; -- unsigned long flags; -- dev = (struct ite8709_device *) data; -- -- spin_lock_irqsave(&dev->hardware_lock, flags); -- dev->device_busy = 1; -- spin_unlock_irqrestore(&dev->hardware_lock, flags); -- -- if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) { -- dprintk("rearming IRQ\n"); -- ite8709_write_register(dev, IT8512_REG_RCR, -- IT8512_RCR_RXACT | CFG_DCR); -- ite8709_write_register(dev, IT8512_REG_MSTCR, -- CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); -- ite8709_write_register(dev, IT8512_REG_RCR, -- IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); -- if (!dev->force_rearm) -- dev->rearmed = 1; -- dev->force_rearm = 0; -- } -- -- spin_lock_irqsave(&dev->hardware_lock, flags); -- dev->device_busy = 0; -- spin_unlock_irqrestore(&dev->hardware_lock, flags); --} -- --static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno, -- char *msg) --{ -- if (msg != NULL) -- printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg); -- -- switch (stage) { -- case 6: -- if (dev->use_count > 0) -- ite8709_drop_hardware(dev); -- case 5: -- free_irq(dev->irq, dev); -- case 4: -- release_region(dev->io, 2); -- case 3: -- lirc_unregister_driver(dev->driver.minor); -- case 2: -- lirc_buffer_free(dev->driver.rbuf); -- kfree(dev->driver.rbuf); -- case 1: -- kfree(dev); -- case 0: -- ; -- } -- -- return errno; --} -- --static int __devinit ite8709_pnp_probe(struct pnp_dev *dev, -- const struct pnp_device_id *dev_id) --{ -- struct lirc_driver *driver; -- struct ite8709_device *ite8709_dev; -- int ret; -- -- /* Check resources validity */ -- if (!pnp_irq_valid(dev, 0)) -- return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ"); -- if (!pnp_port_valid(dev, 2)) -- return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port"); -- -- /* Allocate memory for device struct */ -- ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL); -- if (ite8709_dev == NULL) -- return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed"); -- pnp_set_drvdata(dev, ite8709_dev); -- -- /* Initialize device struct */ -- ite8709_dev->use_count = 0; -- ite8709_dev->irq = pnp_irq(dev, 0); -- ite8709_dev->io = pnp_port_start(dev, 2); -- ite8709_dev->hardware_lock = -- __SPIN_LOCK_UNLOCKED(ite8709_dev->hardware_lock); -- ite8709_dev->acc_pulse = 0; -- ite8709_dev->acc_space = 0; -- ite8709_dev->lastbit = 0; -- do_gettimeofday(&ite8709_dev->last_tv); -- tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq, -- (long) ite8709_dev); -- ite8709_dev->force_rearm = 0; -- ite8709_dev->rearmed = 0; -- ite8709_dev->device_busy = 0; -- -- /* Initialize driver struct */ -- driver = &ite8709_dev->driver; -- strcpy(driver->name, LIRC_DRIVER_NAME); -- driver->minor = -1; -- driver->code_length = sizeof(int) * 8; -- driver->sample_rate = 0; -- driver->features = LIRC_CAN_REC_MODE2; -- driver->data = ite8709_dev; -- driver->add_to_buf = NULL; -- driver->set_use_inc = ite8709_set_use_inc; -- driver->set_use_dec = ite8709_set_use_dec; -- driver->dev = &dev->dev; -- driver->owner = THIS_MODULE; -- -- /* Initialize LIRC buffer */ -- driver->rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); -- if (!driver->rbuf) -- return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, -- "can't allocate lirc_buffer"); -- if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) -- return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, -- "lirc_buffer_init() failed"); -- -- /* Register LIRC driver */ -- ret = lirc_register_driver(driver); -- if (ret < 0) -- return ite8709_cleanup(ite8709_dev, 2, ret, -- "lirc_register_driver() failed"); -- -- /* Reserve I/O port access */ -- if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME)) -- return ite8709_cleanup(ite8709_dev, 3, -EBUSY, -- "i/o port already in use"); -- -- /* Reserve IRQ line */ -- ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0, -- LIRC_DRIVER_NAME, ite8709_dev); -- if (ret < 0) -- return ite8709_cleanup(ite8709_dev, 4, ret, -- "IRQ already in use"); -- -- /* Initialize hardware */ -- ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */ -- -- printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n", -- ite8709_dev->irq, ite8709_dev->io); -- -- return 0; --} -- --static void __devexit ite8709_pnp_remove(struct pnp_dev *dev) --{ -- struct ite8709_device *ite8709_dev; -- ite8709_dev = pnp_get_drvdata(dev); -- -- ite8709_cleanup(ite8709_dev, 6, 0, NULL); -- -- printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n"); --} -- --#ifdef CONFIG_PM --static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state) --{ -- struct ite8709_device *ite8709_dev; -- ite8709_dev = pnp_get_drvdata(dev); -- -- if (ite8709_dev->use_count > 0) -- ite8709_drop_hardware(ite8709_dev); -- -- return 0; --} -- --static int ite8709_pnp_resume(struct pnp_dev *dev) --{ -- struct ite8709_device *ite8709_dev; -- ite8709_dev = pnp_get_drvdata(dev); -- -- if (ite8709_dev->use_count > 0) -- ite8709_init_hardware(ite8709_dev); -- -- return 0; --} --#else --#define ite8709_pnp_suspend NULL --#define ite8709_pnp_resume NULL --#endif -- --static const struct pnp_device_id pnp_dev_table[] = { -- {"ITE8709", 0}, -- {} --}; -- --MODULE_DEVICE_TABLE(pnp, pnp_dev_table); -- --static struct pnp_driver ite8709_pnp_driver = { -- .name = LIRC_DRIVER_NAME, -- .probe = ite8709_pnp_probe, -- .remove = __devexit_p(ite8709_pnp_remove), -- .suspend = ite8709_pnp_suspend, -- .resume = ite8709_pnp_resume, -- .id_table = pnp_dev_table, --}; -- --static int __init ite8709_init_module(void) --{ -- return pnp_register_driver(&ite8709_pnp_driver); --} --module_init(ite8709_init_module); -- --static void __exit ite8709_cleanup_module(void) --{ -- pnp_unregister_driver(&ite8709_pnp_driver); --} --module_exit(ite8709_cleanup_module); -- --MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port"); --MODULE_AUTHOR("Grégory Lardière"); --MODULE_LICENSE("GPL"); -- --module_param(debug, bool, S_IRUGO | S_IWUSR); --MODULE_PARM_DESC(debug, "Enable debugging messages"); -diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c -index 925eabe..63a438d 100644 ---- a/drivers/staging/lirc/lirc_sasem.c -+++ b/drivers/staging/lirc/lirc_sasem.c -@@ -364,7 +364,7 @@ static ssize_t vfd_write(struct file *file, const char *buf, - int i; - int retval = 0; - struct sasem_context *context; -- int *data_buf; -+ int *data_buf = NULL; - - context = (struct sasem_context *) file->private_data; - if (!context) { -diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c -index 0aad0d7..dd6a57c 100644 ---- a/drivers/staging/lirc/lirc_zilog.c -+++ b/drivers/staging/lirc/lirc_zilog.c -@@ -63,14 +63,16 @@ - #include - #include - -+struct IR; -+ - struct IR_rx { -+ struct kref ref; -+ struct IR *ir; -+ - /* RX device */ -+ struct mutex client_lock; - struct i2c_client *c; - -- /* RX device buffer & lock */ -- struct lirc_buffer buf; -- struct mutex buf_lock; -- - /* RX polling thread data */ - struct task_struct *task; - -@@ -80,7 +82,11 @@ struct IR_rx { - }; - - struct IR_tx { -+ struct kref ref; -+ struct IR *ir; -+ - /* TX device */ -+ struct mutex client_lock; - struct i2c_client *c; - - /* TX additional actions needed */ -@@ -89,19 +95,34 @@ struct IR_tx { - }; - - struct IR { -+ struct kref ref; -+ struct list_head list; -+ -+ /* FIXME spinlock access to l.features */ - struct lirc_driver l; -+ struct lirc_buffer rbuf; - - struct mutex ir_lock; -- int open; -+ atomic_t open_count; - - struct i2c_adapter *adapter; -+ -+ spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */ - struct IR_rx *rx; -+ -+ spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */ - struct IR_tx *tx; - }; - --/* Minor -> data mapping */ --static struct mutex ir_devices_lock; --static struct IR *ir_devices[MAX_IRCTL_DEVICES]; -+/* IR transceiver instance object list */ -+/* -+ * This lock is used for the following: -+ * a. ir_devices_list access, insertions, deletions -+ * b. struct IR kref get()s and put()s -+ * c. serialization of ir_probe() for the two i2c_clients for a Z8 -+ */ -+static DEFINE_MUTEX(ir_devices_lock); -+static LIST_HEAD(ir_devices_list); - - /* Block size for IR transmitter */ - #define TX_BLOCK_SIZE 99 -@@ -147,6 +168,157 @@ static int minor = -1; /* minor number */ - ## args); \ - } while (0) - -+ -+/* struct IR reference counting */ -+static struct IR *get_ir_device(struct IR *ir, bool ir_devices_lock_held) -+{ -+ if (ir_devices_lock_held) { -+ kref_get(&ir->ref); -+ } else { -+ mutex_lock(&ir_devices_lock); -+ kref_get(&ir->ref); -+ mutex_unlock(&ir_devices_lock); -+ } -+ return ir; -+} -+ -+static void release_ir_device(struct kref *ref) -+{ -+ struct IR *ir = container_of(ref, struct IR, ref); -+ -+ /* -+ * Things should be in this state by now: -+ * ir->rx set to NULL and deallocated - happens before ir->rx->ir put() -+ * ir->rx->task kthread stopped - happens before ir->rx->ir put() -+ * ir->tx set to NULL and deallocated - happens before ir->tx->ir put() -+ * ir->open_count == 0 - happens on final close() -+ * ir_lock, tx_ref_lock, rx_ref_lock, all released -+ */ -+ if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) { -+ lirc_unregister_driver(ir->l.minor); -+ ir->l.minor = MAX_IRCTL_DEVICES; -+ } -+ if (ir->rbuf.fifo_initialized) -+ lirc_buffer_free(&ir->rbuf); -+ list_del(&ir->list); -+ kfree(ir); -+} -+ -+static int put_ir_device(struct IR *ir, bool ir_devices_lock_held) -+{ -+ int released; -+ -+ if (ir_devices_lock_held) -+ return kref_put(&ir->ref, release_ir_device); -+ -+ mutex_lock(&ir_devices_lock); -+ released = kref_put(&ir->ref, release_ir_device); -+ mutex_unlock(&ir_devices_lock); -+ -+ return released; -+} -+ -+/* struct IR_rx reference counting */ -+static struct IR_rx *get_ir_rx(struct IR *ir) -+{ -+ struct IR_rx *rx; -+ -+ spin_lock(&ir->rx_ref_lock); -+ rx = ir->rx; -+ if (rx != NULL) -+ kref_get(&rx->ref); -+ spin_unlock(&ir->rx_ref_lock); -+ return rx; -+} -+ -+static void destroy_rx_kthread(struct IR_rx *rx, bool ir_devices_lock_held) -+{ -+ /* end up polling thread */ -+ if (!IS_ERR_OR_NULL(rx->task)) { -+ kthread_stop(rx->task); -+ rx->task = NULL; -+ /* Put the ir ptr that ir_probe() gave to the rx poll thread */ -+ put_ir_device(rx->ir, ir_devices_lock_held); -+ } -+} -+ -+static void release_ir_rx(struct kref *ref) -+{ -+ struct IR_rx *rx = container_of(ref, struct IR_rx, ref); -+ struct IR *ir = rx->ir; -+ -+ /* -+ * This release function can't do all the work, as we want -+ * to keep the rx_ref_lock a spinlock, and killing the poll thread -+ * and releasing the ir reference can cause a sleep. That work is -+ * performed by put_ir_rx() -+ */ -+ ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; -+ /* Don't put_ir_device(rx->ir) here; lock can't be freed yet */ -+ ir->rx = NULL; -+ /* Don't do the kfree(rx) here; we still need to kill the poll thread */ -+ return; -+} -+ -+static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held) -+{ -+ int released; -+ struct IR *ir = rx->ir; -+ -+ spin_lock(&ir->rx_ref_lock); -+ released = kref_put(&rx->ref, release_ir_rx); -+ spin_unlock(&ir->rx_ref_lock); -+ /* Destroy the rx kthread while not holding the spinlock */ -+ if (released) { -+ destroy_rx_kthread(rx, ir_devices_lock_held); -+ kfree(rx); -+ /* Make sure we're not still in a poll_table somewhere */ -+ wake_up_interruptible(&ir->rbuf.wait_poll); -+ } -+ /* Do a reference put() for the rx->ir reference, if we released rx */ -+ if (released) -+ put_ir_device(ir, ir_devices_lock_held); -+ return released; -+} -+ -+/* struct IR_tx reference counting */ -+static struct IR_tx *get_ir_tx(struct IR *ir) -+{ -+ struct IR_tx *tx; -+ -+ spin_lock(&ir->tx_ref_lock); -+ tx = ir->tx; -+ if (tx != NULL) -+ kref_get(&tx->ref); -+ spin_unlock(&ir->tx_ref_lock); -+ return tx; -+} -+ -+static void release_ir_tx(struct kref *ref) -+{ -+ struct IR_tx *tx = container_of(ref, struct IR_tx, ref); -+ struct IR *ir = tx->ir; -+ -+ ir->l.features &= ~LIRC_CAN_SEND_PULSE; -+ /* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */ -+ ir->tx = NULL; -+ kfree(tx); -+} -+ -+static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held) -+{ -+ int released; -+ struct IR *ir = tx->ir; -+ -+ spin_lock(&ir->tx_ref_lock); -+ released = kref_put(&tx->ref, release_ir_tx); -+ spin_unlock(&ir->tx_ref_lock); -+ /* Do a reference put() for the tx->ir reference, if we released tx */ -+ if (released) -+ put_ir_device(ir, ir_devices_lock_held); -+ return released; -+} -+ - static int add_to_buf(struct IR *ir) - { - __u16 code; -@@ -156,23 +328,38 @@ static int add_to_buf(struct IR *ir) - int ret; - int failures = 0; - unsigned char sendbuf[1] = { 0 }; -- struct IR_rx *rx = ir->rx; -+ struct lirc_buffer *rbuf = ir->l.rbuf; -+ struct IR_rx *rx; -+ struct IR_tx *tx; - -+ if (lirc_buffer_full(rbuf)) { -+ dprintk("buffer overflow\n"); -+ return -EOVERFLOW; -+ } -+ -+ rx = get_ir_rx(ir); - if (rx == NULL) - return -ENXIO; - -- if (lirc_buffer_full(&rx->buf)) { -- dprintk("buffer overflow\n"); -- return -EOVERFLOW; -+ /* Ensure our rx->c i2c_client remains valid for the duration */ -+ mutex_lock(&rx->client_lock); -+ if (rx->c == NULL) { -+ mutex_unlock(&rx->client_lock); -+ put_ir_rx(rx, false); -+ return -ENXIO; - } - -+ tx = get_ir_tx(ir); -+ - /* - * service the device as long as it is returning - * data and we have space - */ - do { -- if (kthread_should_stop()) -- return -ENODATA; -+ if (kthread_should_stop()) { -+ ret = -ENODATA; -+ break; -+ } - - /* - * Lock i2c bus for the duration. RX/TX chips interfere so -@@ -182,7 +369,8 @@ static int add_to_buf(struct IR *ir) - - if (kthread_should_stop()) { - mutex_unlock(&ir->ir_lock); -- return -ENODATA; -+ ret = -ENODATA; -+ break; - } - - /* -@@ -196,7 +384,7 @@ static int add_to_buf(struct IR *ir) - mutex_unlock(&ir->ir_lock); - zilog_error("unable to read from the IR chip " - "after 3 resets, giving up\n"); -- return ret; -+ break; - } - - /* Looks like the chip crashed, reset it */ -@@ -206,19 +394,23 @@ static int add_to_buf(struct IR *ir) - set_current_state(TASK_UNINTERRUPTIBLE); - if (kthread_should_stop()) { - mutex_unlock(&ir->ir_lock); -- return -ENODATA; -+ ret = -ENODATA; -+ break; - } - schedule_timeout((100 * HZ + 999) / 1000); -- ir->tx->need_boot = 1; -+ if (tx != NULL) -+ tx->need_boot = 1; - - ++failures; - mutex_unlock(&ir->ir_lock); -+ ret = 0; - continue; - } - - if (kthread_should_stop()) { - mutex_unlock(&ir->ir_lock); -- return -ENODATA; -+ ret = -ENODATA; -+ break; - } - ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf)); - mutex_unlock(&ir->ir_lock); -@@ -234,12 +426,17 @@ static int add_to_buf(struct IR *ir) - - /* key pressed ? */ - if (rx->hdpvr_data_fmt) { -- if (got_data && (keybuf[0] == 0x80)) -- return 0; -- else if (got_data && (keybuf[0] == 0x00)) -- return -ENODATA; -- } else if ((rx->b[0] & 0x80) == 0) -- return got_data ? 0 : -ENODATA; -+ if (got_data && (keybuf[0] == 0x80)) { -+ ret = 0; -+ break; -+ } else if (got_data && (keybuf[0] == 0x00)) { -+ ret = -ENODATA; -+ break; -+ } -+ } else if ((rx->b[0] & 0x80) == 0) { -+ ret = got_data ? 0 : -ENODATA; -+ break; -+ } - - /* look what we have */ - code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2); -@@ -248,11 +445,16 @@ static int add_to_buf(struct IR *ir) - codes[1] = code & 0xff; - - /* return it */ -- lirc_buffer_write(&rx->buf, codes); -+ lirc_buffer_write(rbuf, codes); - ++got_data; -- } while (!lirc_buffer_full(&rx->buf)); -+ ret = 0; -+ } while (!lirc_buffer_full(rbuf)); - -- return 0; -+ mutex_unlock(&rx->client_lock); -+ if (tx != NULL) -+ put_ir_tx(tx, false); -+ put_ir_rx(rx, false); -+ return ret; - } - - /* -@@ -268,19 +470,19 @@ static int add_to_buf(struct IR *ir) - static int lirc_thread(void *arg) - { - struct IR *ir = arg; -- struct IR_rx *rx = ir->rx; -+ struct lirc_buffer *rbuf = ir->l.rbuf; - - dprintk("poll thread started\n"); - - while (!kthread_should_stop()) { -- set_current_state(TASK_INTERRUPTIBLE); -- - /* if device not opened, we can sleep half a second */ -- if (!ir->open) { -+ if (atomic_read(&ir->open_count) == 0) { - schedule_timeout(HZ/2); - continue; - } - -+ set_current_state(TASK_INTERRUPTIBLE); -+ - /* - * This is ~113*2 + 24 + jitter (2*repeat gap + code length). - * We use this interval as the chip resets every time you poll -@@ -295,7 +497,7 @@ static int lirc_thread(void *arg) - if (kthread_should_stop()) - break; - if (!add_to_buf(ir)) -- wake_up_interruptible(&rx->buf.wait_poll); -+ wake_up_interruptible(&rbuf->wait_poll); - } - - dprintk("poll thread ended\n"); -@@ -304,34 +506,12 @@ static int lirc_thread(void *arg) - - static int set_use_inc(void *data) - { -- struct IR *ir = data; -- -- if (ir->l.owner == NULL || try_module_get(ir->l.owner) == 0) -- return -ENODEV; -- -- /* lock bttv in memory while /dev/lirc is in use */ -- /* -- * this is completely broken code. lirc_unregister_driver() -- * must be possible even when the device is open -- */ -- if (ir->rx != NULL) -- i2c_use_client(ir->rx->c); -- if (ir->tx != NULL) -- i2c_use_client(ir->tx->c); -- - return 0; - } - - static void set_use_dec(void *data) - { -- struct IR *ir = data; -- -- if (ir->rx) -- i2c_release_client(ir->rx->c); -- if (ir->tx) -- i2c_release_client(ir->tx->c); -- if (ir->l.owner != NULL) -- module_put(ir->l.owner); -+ return; - } - - /* safe read of a uint32 (always network byte order) */ -@@ -585,7 +765,7 @@ static int fw_load(struct IR_tx *tx) - } - - /* Request codeset data file */ -- ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &tx->c->dev); -+ ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev); - if (ret != 0) { - zilog_error("firmware haup-ir-blaster.bin not available " - "(%d)\n", ret); -@@ -711,59 +891,32 @@ out: - return ret; - } - --/* initialise the IR TX device */ --static int tx_init(struct IR_tx *tx) --{ -- int ret; -- -- /* Load 'firmware' */ -- ret = fw_load(tx); -- if (ret != 0) -- return ret; -- -- /* Send boot block */ -- ret = send_boot_data(tx); -- if (ret != 0) -- return ret; -- tx->need_boot = 0; -- -- /* Looks good */ -- return 0; --} -- --/* do nothing stub to make LIRC happy */ --static loff_t lseek(struct file *filep, loff_t offset, int orig) --{ -- return -ESPIPE; --} -- - /* copied from lirc_dev */ - static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) - { - struct IR *ir = filep->private_data; -- struct IR_rx *rx = ir->rx; -- int ret = 0, written = 0; -+ struct IR_rx *rx; -+ struct lirc_buffer *rbuf = ir->l.rbuf; -+ int ret = 0, written = 0, retries = 0; -+ unsigned int m; - DECLARE_WAITQUEUE(wait, current); - - dprintk("read called\n"); -- if (rx == NULL) -- return -ENODEV; -- -- if (mutex_lock_interruptible(&rx->buf_lock)) -- return -ERESTARTSYS; -- -- if (n % rx->buf.chunk_size) { -+ if (n % rbuf->chunk_size) { - dprintk("read result = -EINVAL\n"); -- mutex_unlock(&rx->buf_lock); - return -EINVAL; - } - -+ rx = get_ir_rx(ir); -+ if (rx == NULL) -+ return -ENXIO; -+ - /* - * we add ourselves to the task queue before buffer check - * to avoid losing scan code (in case when queue is awaken somewhere - * between while condition checking and scheduling) - */ -- add_wait_queue(&rx->buf.wait_poll, &wait); -+ add_wait_queue(&rbuf->wait_poll, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - /* -@@ -771,7 +924,7 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) - * mode and 'copy_to_user' is happy, wait for data. - */ - while (written < n && ret == 0) { -- if (lirc_buffer_empty(&rx->buf)) { -+ if (lirc_buffer_empty(rbuf)) { - /* - * According to the read(2) man page, 'written' can be - * returned as less than 'n', instead of blocking -@@ -791,20 +944,27 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } else { -- unsigned char buf[rx->buf.chunk_size]; -- lirc_buffer_read(&rx->buf, buf); -- ret = copy_to_user((void *)outbuf+written, buf, -- rx->buf.chunk_size); -- written += rx->buf.chunk_size; -+ unsigned char buf[rbuf->chunk_size]; -+ m = lirc_buffer_read(rbuf, buf); -+ if (m == rbuf->chunk_size) { -+ ret = copy_to_user((void *)outbuf+written, buf, -+ rbuf->chunk_size); -+ written += rbuf->chunk_size; -+ } else { -+ retries++; -+ } -+ if (retries >= 5) { -+ zilog_error("Buffer read failed!\n"); -+ ret = -EIO; -+ } - } - } - -- remove_wait_queue(&rx->buf.wait_poll, &wait); -+ remove_wait_queue(&rbuf->wait_poll, &wait); -+ put_ir_rx(rx, false); - set_current_state(TASK_RUNNING); -- mutex_unlock(&rx->buf_lock); - -- dprintk("read result = %s (%d)\n", -- ret ? "-EFAULT" : "OK", ret); -+ dprintk("read result = %d (%s)\n", ret, ret ? "Error" : "OK"); - - return ret ? ret : written; - } -@@ -931,17 +1091,27 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, - loff_t *ppos) - { - struct IR *ir = filep->private_data; -- struct IR_tx *tx = ir->tx; -+ struct IR_tx *tx; - size_t i; - int failures = 0; - -- if (tx == NULL) -- return -ENODEV; -- - /* Validate user parameters */ - if (n % sizeof(int)) - return -EINVAL; - -+ /* Get a struct IR_tx reference */ -+ tx = get_ir_tx(ir); -+ if (tx == NULL) -+ return -ENXIO; -+ -+ /* Ensure our tx->c i2c_client remains valid for the duration */ -+ mutex_lock(&tx->client_lock); -+ if (tx->c == NULL) { -+ mutex_unlock(&tx->client_lock); -+ put_ir_tx(tx, false); -+ return -ENXIO; -+ } -+ - /* Lock i2c bus for the duration */ - mutex_lock(&ir->ir_lock); - -@@ -952,11 +1122,24 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, - - if (copy_from_user(&command, buf + i, sizeof(command))) { - mutex_unlock(&ir->ir_lock); -+ mutex_unlock(&tx->client_lock); -+ put_ir_tx(tx, false); - return -EFAULT; - } - - /* Send boot data first if required */ - if (tx->need_boot == 1) { -+ /* Make sure we have the 'firmware' loaded, first */ -+ ret = fw_load(tx); -+ if (ret != 0) { -+ mutex_unlock(&ir->ir_lock); -+ mutex_unlock(&tx->client_lock); -+ put_ir_tx(tx, false); -+ if (ret != -ENOMEM) -+ ret = -EIO; -+ return ret; -+ } -+ /* Prep the chip for transmitting codes */ - ret = send_boot_data(tx); - if (ret == 0) - tx->need_boot = 0; -@@ -968,6 +1151,8 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, - (unsigned)command & 0xFFFF); - if (ret == -EPROTO) { - mutex_unlock(&ir->ir_lock); -+ mutex_unlock(&tx->client_lock); -+ put_ir_tx(tx, false); - return ret; - } - } -@@ -985,6 +1170,8 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, - zilog_error("unable to send to the IR chip " - "after 3 resets, giving up\n"); - mutex_unlock(&ir->ir_lock); -+ mutex_unlock(&tx->client_lock); -+ put_ir_tx(tx, false); - return ret; - } - set_current_state(TASK_UNINTERRUPTIBLE); -@@ -998,6 +1185,11 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, - /* Release i2c bus */ - mutex_unlock(&ir->ir_lock); - -+ mutex_unlock(&tx->client_lock); -+ -+ /* Give back our struct IR_tx reference */ -+ put_ir_tx(tx, false); -+ - /* All looks good */ - return n; - } -@@ -1006,23 +1198,32 @@ static ssize_t write(struct file *filep, const char *buf, size_t n, - static unsigned int poll(struct file *filep, poll_table *wait) - { - struct IR *ir = filep->private_data; -- struct IR_rx *rx = ir->rx; -+ struct IR_rx *rx; -+ struct lirc_buffer *rbuf = ir->l.rbuf; - unsigned int ret; - - dprintk("poll called\n"); -- if (rx == NULL) -- return -ENODEV; -- -- mutex_lock(&rx->buf_lock); - -- poll_wait(filep, &rx->buf.wait_poll, wait); -+ rx = get_ir_rx(ir); -+ if (rx == NULL) { -+ /* -+ * Revisit this, if our poll function ever reports writeable -+ * status for Tx -+ */ -+ dprintk("poll result = POLLERR\n"); -+ return POLLERR; -+ } - -- dprintk("poll result = %s\n", -- lirc_buffer_empty(&rx->buf) ? "0" : "POLLIN|POLLRDNORM"); -+ /* -+ * Add our lirc_buffer's wait_queue to the poll_table. A wake up on -+ * that buffer's wait queue indicates we may have a new poll status. -+ */ -+ poll_wait(filep, &rbuf->wait_poll, wait); - -- ret = lirc_buffer_empty(&rx->buf) ? 0 : (POLLIN|POLLRDNORM); -+ /* Indicate what ops could happen immediately without blocking */ -+ ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM); - -- mutex_unlock(&rx->buf_lock); -+ dprintk("poll result = %s\n", ret ? "POLLIN|POLLRDNORM" : "none"); - return ret; - } - -@@ -1030,11 +1231,9 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) - { - struct IR *ir = filep->private_data; - int result; -- unsigned long mode, features = 0; -+ unsigned long mode, features; - -- features |= LIRC_CAN_SEND_PULSE; -- if (ir->rx != NULL) -- features |= LIRC_CAN_REC_LIRCCODE; -+ features = ir->l.features; - - switch (cmd) { - case LIRC_GET_LENGTH: -@@ -1061,9 +1260,15 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) - result = -EINVAL; - break; - case LIRC_GET_SEND_MODE: -+ if (!(features&LIRC_CAN_SEND_MASK)) -+ return -ENOSYS; -+ - result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); - break; - case LIRC_SET_SEND_MODE: -+ if (!(features&LIRC_CAN_SEND_MASK)) -+ return -ENOSYS; -+ - result = get_user(mode, (unsigned long *) arg); - if (!result && mode != LIRC_MODE_PULSE) - return -EINVAL; -@@ -1074,13 +1279,24 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) - return result; - } - --/* ir_devices_lock must be held */ --static struct IR *find_ir_device_by_minor(unsigned int minor) -+static struct IR *get_ir_device_by_minor(unsigned int minor) - { -- if (minor >= MAX_IRCTL_DEVICES) -- return NULL; -+ struct IR *ir; -+ struct IR *ret = NULL; -+ -+ mutex_lock(&ir_devices_lock); -+ -+ if (!list_empty(&ir_devices_list)) { -+ list_for_each_entry(ir, &ir_devices_list, list) { -+ if (ir->l.minor == minor) { -+ ret = get_ir_device(ir, true); -+ break; -+ } -+ } -+ } - -- return ir_devices[minor]; -+ mutex_unlock(&ir_devices_lock); -+ return ret; - } - - /* -@@ -1090,31 +1306,20 @@ static struct IR *find_ir_device_by_minor(unsigned int minor) - static int open(struct inode *node, struct file *filep) - { - struct IR *ir; -- int ret; - unsigned int minor = MINOR(node->i_rdev); - - /* find our IR struct */ -- mutex_lock(&ir_devices_lock); -- ir = find_ir_device_by_minor(minor); -- mutex_unlock(&ir_devices_lock); -+ ir = get_ir_device_by_minor(minor); - - if (ir == NULL) - return -ENODEV; - -- /* increment in use count */ -- mutex_lock(&ir->ir_lock); -- ++ir->open; -- ret = set_use_inc(ir); -- if (ret != 0) { -- --ir->open; -- mutex_unlock(&ir->ir_lock); -- return ret; -- } -- mutex_unlock(&ir->ir_lock); -+ atomic_inc(&ir->open_count); - - /* stash our IR struct */ - filep->private_data = ir; - -+ nonseekable_open(node, filep); - return 0; - } - -@@ -1128,22 +1333,12 @@ static int close(struct inode *node, struct file *filep) - return -ENODEV; - } - -- /* decrement in use count */ -- mutex_lock(&ir->ir_lock); -- --ir->open; -- set_use_dec(ir); -- mutex_unlock(&ir->ir_lock); -+ atomic_dec(&ir->open_count); - -+ put_ir_device(ir, false); - return 0; - } - --static struct lirc_driver lirc_template = { -- .name = "lirc_zilog", -- .set_use_inc = set_use_inc, -- .set_use_dec = set_use_dec, -- .owner = THIS_MODULE --}; -- - static int ir_remove(struct i2c_client *client); - static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); - -@@ -1170,7 +1365,7 @@ static struct i2c_driver driver = { - - static const struct file_operations lirc_fops = { - .owner = THIS_MODULE, -- .llseek = lseek, -+ .llseek = no_llseek, - .read = read, - .write = write, - .poll = poll, -@@ -1182,97 +1377,64 @@ static const struct file_operations lirc_fops = { - .release = close - }; - --static void destroy_rx_kthread(struct IR_rx *rx) --{ -- /* end up polling thread */ -- if (rx != NULL && !IS_ERR_OR_NULL(rx->task)) { -- kthread_stop(rx->task); -- rx->task = NULL; -- } --} -+static struct lirc_driver lirc_template = { -+ .name = "lirc_zilog", -+ .minor = -1, -+ .code_length = 13, -+ .buffer_size = BUFLEN / 2, -+ .sample_rate = 0, /* tell lirc_dev to not start its own kthread */ -+ .chunk_size = 2, -+ .set_use_inc = set_use_inc, -+ .set_use_dec = set_use_dec, -+ .fops = &lirc_fops, -+ .owner = THIS_MODULE, -+}; - --/* ir_devices_lock must be held */ --static int add_ir_device(struct IR *ir) -+static int ir_remove(struct i2c_client *client) - { -- int i; -- -- for (i = 0; i < MAX_IRCTL_DEVICES; i++) -- if (ir_devices[i] == NULL) { -- ir_devices[i] = ir; -- break; -+ if (strncmp("ir_tx_z8", client->name, 8) == 0) { -+ struct IR_tx *tx = i2c_get_clientdata(client); -+ if (tx != NULL) { -+ mutex_lock(&tx->client_lock); -+ tx->c = NULL; -+ mutex_unlock(&tx->client_lock); -+ put_ir_tx(tx, false); - } -- -- return i == MAX_IRCTL_DEVICES ? -ENOMEM : i; --} -- --/* ir_devices_lock must be held */ --static void del_ir_device(struct IR *ir) --{ -- int i; -- -- for (i = 0; i < MAX_IRCTL_DEVICES; i++) -- if (ir_devices[i] == ir) { -- ir_devices[i] = NULL; -- break; -+ } else if (strncmp("ir_rx_z8", client->name, 8) == 0) { -+ struct IR_rx *rx = i2c_get_clientdata(client); -+ if (rx != NULL) { -+ mutex_lock(&rx->client_lock); -+ rx->c = NULL; -+ mutex_unlock(&rx->client_lock); -+ put_ir_rx(rx, false); - } --} -- --static int ir_remove(struct i2c_client *client) --{ -- struct IR *ir = i2c_get_clientdata(client); -- -- mutex_lock(&ir_devices_lock); -- -- if (ir == NULL) { -- /* We destroyed everything when the first client came through */ -- mutex_unlock(&ir_devices_lock); -- return 0; - } -- -- /* Good-bye LIRC */ -- lirc_unregister_driver(ir->l.minor); -- -- /* Good-bye Rx */ -- destroy_rx_kthread(ir->rx); -- if (ir->rx != NULL) { -- if (ir->rx->buf.fifo_initialized) -- lirc_buffer_free(&ir->rx->buf); -- i2c_set_clientdata(ir->rx->c, NULL); -- kfree(ir->rx); -- } -- -- /* Good-bye Tx */ -- i2c_set_clientdata(ir->tx->c, NULL); -- kfree(ir->tx); -- -- /* Good-bye IR */ -- del_ir_device(ir); -- kfree(ir); -- -- mutex_unlock(&ir_devices_lock); - return 0; - } - - - /* ir_devices_lock must be held */ --static struct IR *find_ir_device_by_adapter(struct i2c_adapter *adapter) -+static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter) - { -- int i; -- struct IR *ir = NULL; -+ struct IR *ir; - -- for (i = 0; i < MAX_IRCTL_DEVICES; i++) -- if (ir_devices[i] != NULL && -- ir_devices[i]->adapter == adapter) { -- ir = ir_devices[i]; -- break; -+ if (list_empty(&ir_devices_list)) -+ return NULL; -+ -+ list_for_each_entry(ir, &ir_devices_list, list) -+ if (ir->adapter == adapter) { -+ get_ir_device(ir, true); -+ return ir; - } - -- return ir; -+ return NULL; - } - - static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) - { - struct IR *ir; -+ struct IR_tx *tx; -+ struct IR_rx *rx; - struct i2c_adapter *adap = client->adapter; - int ret; - bool tx_probe = false; -@@ -1296,133 +1458,170 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) - mutex_lock(&ir_devices_lock); - - /* Use a single struct IR instance for both the Rx and Tx functions */ -- ir = find_ir_device_by_adapter(adap); -+ ir = get_ir_device_by_adapter(adap); - if (ir == NULL) { - ir = kzalloc(sizeof(struct IR), GFP_KERNEL); - if (ir == NULL) { - ret = -ENOMEM; - goto out_no_ir; - } -+ kref_init(&ir->ref); -+ - /* store for use in ir_probe() again, and open() later on */ -- ret = add_ir_device(ir); -- if (ret) -- goto out_free_ir; -+ INIT_LIST_HEAD(&ir->list); -+ list_add_tail(&ir->list, &ir_devices_list); - - ir->adapter = adap; - mutex_init(&ir->ir_lock); -+ atomic_set(&ir->open_count, 0); -+ spin_lock_init(&ir->tx_ref_lock); -+ spin_lock_init(&ir->rx_ref_lock); - - /* set lirc_dev stuff */ - memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); -- ir->l.minor = minor; /* module option */ -- ir->l.code_length = 13; -- ir->l.rbuf = NULL; -- ir->l.fops = &lirc_fops; -- ir->l.data = ir; -- ir->l.dev = &adap->dev; -- ir->l.sample_rate = 0; -+ /* -+ * FIXME this is a pointer reference to us, but no refcount. -+ * -+ * This OK for now, since lirc_dev currently won't touch this -+ * buffer as we provide our own lirc_fops. -+ * -+ * Currently our own lirc_fops rely on this ir->l.rbuf pointer -+ */ -+ ir->l.rbuf = &ir->rbuf; -+ ir->l.dev = &adap->dev; -+ ret = lirc_buffer_init(ir->l.rbuf, -+ ir->l.chunk_size, ir->l.buffer_size); -+ if (ret) -+ goto out_put_ir; - } - - if (tx_probe) { -+ /* Get the IR_rx instance for later, if already allocated */ -+ rx = get_ir_rx(ir); -+ - /* Set up a struct IR_tx instance */ -- ir->tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); -- if (ir->tx == NULL) { -+ tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); -+ if (tx == NULL) { - ret = -ENOMEM; -- goto out_free_xx; -+ goto out_put_xx; - } -- -- ir->tx->c = client; -- ir->tx->need_boot = 1; -- ir->tx->post_tx_ready_poll = -+ kref_init(&tx->ref); -+ ir->tx = tx; -+ -+ ir->l.features |= LIRC_CAN_SEND_PULSE; -+ mutex_init(&tx->client_lock); -+ tx->c = client; -+ tx->need_boot = 1; -+ tx->post_tx_ready_poll = - (id->driver_data & ID_FLAG_HDPVR) ? false : true; -+ -+ /* An ir ref goes to the struct IR_tx instance */ -+ tx->ir = get_ir_device(ir, true); -+ -+ /* A tx ref goes to the i2c_client */ -+ i2c_set_clientdata(client, get_ir_tx(ir)); -+ -+ /* -+ * Load the 'firmware'. We do this before registering with -+ * lirc_dev, so the first firmware load attempt does not happen -+ * after a open() or write() call on the device. -+ * -+ * Failure here is not deemed catastrophic, so the receiver will -+ * still be usable. Firmware load will be retried in write(), -+ * if it is needed. -+ */ -+ fw_load(tx); -+ -+ /* Proceed only if the Rx client is also ready or not needed */ -+ if (rx == NULL && !tx_only) { -+ zilog_info("probe of IR Tx on %s (i2c-%d) done. Waiting" -+ " on IR Rx.\n", adap->name, adap->nr); -+ goto out_ok; -+ } - } else { -+ /* Get the IR_tx instance for later, if already allocated */ -+ tx = get_ir_tx(ir); -+ - /* Set up a struct IR_rx instance */ -- ir->rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); -- if (ir->rx == NULL) { -+ rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); -+ if (rx == NULL) { - ret = -ENOMEM; -- goto out_free_xx; -+ goto out_put_xx; - } -+ kref_init(&rx->ref); -+ ir->rx = rx; - -- ret = lirc_buffer_init(&ir->rx->buf, 2, BUFLEN / 2); -- if (ret) -- goto out_free_xx; -- -- mutex_init(&ir->rx->buf_lock); -- ir->rx->c = client; -- ir->rx->hdpvr_data_fmt = -+ ir->l.features |= LIRC_CAN_REC_LIRCCODE; -+ mutex_init(&rx->client_lock); -+ rx->c = client; -+ rx->hdpvr_data_fmt = - (id->driver_data & ID_FLAG_HDPVR) ? true : false; - -- /* set lirc_dev stuff */ -- ir->l.rbuf = &ir->rx->buf; -- } -- -- i2c_set_clientdata(client, ir); -+ /* An ir ref goes to the struct IR_rx instance */ -+ rx->ir = get_ir_device(ir, true); - -- /* Proceed only if we have the required Tx and Rx clients ready to go */ -- if (ir->tx == NULL || -- (ir->rx == NULL && !tx_only)) { -- zilog_info("probe of IR %s on %s (i2c-%d) done. Waiting on " -- "IR %s.\n", tx_probe ? "Tx" : "Rx", adap->name, -- adap->nr, tx_probe ? "Rx" : "Tx"); -- goto out_ok; -- } -+ /* An rx ref goes to the i2c_client */ -+ i2c_set_clientdata(client, get_ir_rx(ir)); - -- /* initialise RX device */ -- if (ir->rx != NULL) { -- /* try to fire up polling thread */ -- ir->rx->task = kthread_run(lirc_thread, ir, -- "zilog-rx-i2c-%d", adap->nr); -- if (IS_ERR(ir->rx->task)) { -- ret = PTR_ERR(ir->rx->task); -+ /* -+ * Start the polling thread. -+ * It will only perform an empty loop around schedule_timeout() -+ * until we register with lirc_dev and the first user open() -+ */ -+ /* An ir ref goes to the new rx polling kthread */ -+ rx->task = kthread_run(lirc_thread, get_ir_device(ir, true), -+ "zilog-rx-i2c-%d", adap->nr); -+ if (IS_ERR(rx->task)) { -+ ret = PTR_ERR(rx->task); - zilog_error("%s: could not start IR Rx polling thread" - "\n", __func__); -- goto out_free_xx; -+ /* Failed kthread, so put back the ir ref */ -+ put_ir_device(ir, true); -+ /* Failure exit, so put back rx ref from i2c_client */ -+ i2c_set_clientdata(client, NULL); -+ put_ir_rx(rx, true); -+ ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; -+ goto out_put_xx; -+ } -+ -+ /* Proceed only if the Tx client is also ready */ -+ if (tx == NULL) { -+ zilog_info("probe of IR Rx on %s (i2c-%d) done. Waiting" -+ " on IR Tx.\n", adap->name, adap->nr); -+ goto out_ok; - } - } - - /* register with lirc */ -+ ir->l.minor = minor; /* module option: user requested minor number */ - ir->l.minor = lirc_register_driver(&ir->l); - if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { - zilog_error("%s: \"minor\" must be between 0 and %d (%d)!\n", - __func__, MAX_IRCTL_DEVICES-1, ir->l.minor); - ret = -EBADRQC; -- goto out_free_thread; -+ goto out_put_xx; - } -+ zilog_info("IR unit on %s (i2c-%d) registered as lirc%d and ready\n", -+ adap->name, adap->nr, ir->l.minor); - -- /* -- * if we have the tx device, load the 'firmware'. We do this -- * after registering with lirc as otherwise hotplug seems to take -- * 10s to create the lirc device. -- */ -- ret = tx_init(ir->tx); -- if (ret != 0) -- goto out_unregister; -- -- zilog_info("probe of IR %s on %s (i2c-%d) done. IR unit ready.\n", -- tx_probe ? "Tx" : "Rx", adap->name, adap->nr); - out_ok: -+ if (rx != NULL) -+ put_ir_rx(rx, true); -+ if (tx != NULL) -+ put_ir_tx(tx, true); -+ put_ir_device(ir, true); -+ zilog_info("probe of IR %s on %s (i2c-%d) done\n", -+ tx_probe ? "Tx" : "Rx", adap->name, adap->nr); - mutex_unlock(&ir_devices_lock); - return 0; - --out_unregister: -- lirc_unregister_driver(ir->l.minor); --out_free_thread: -- destroy_rx_kthread(ir->rx); --out_free_xx: -- if (ir->rx != NULL) { -- if (ir->rx->buf.fifo_initialized) -- lirc_buffer_free(&ir->rx->buf); -- if (ir->rx->c != NULL) -- i2c_set_clientdata(ir->rx->c, NULL); -- kfree(ir->rx); -- } -- if (ir->tx != NULL) { -- if (ir->tx->c != NULL) -- i2c_set_clientdata(ir->tx->c, NULL); -- kfree(ir->tx); -- } --out_free_ir: -- del_ir_device(ir); -- kfree(ir); -+out_put_xx: -+ if (rx != NULL) -+ put_ir_rx(rx, true); -+ if (tx != NULL) -+ put_ir_tx(tx, true); -+out_put_ir: -+ put_ir_device(ir, true); - out_no_ir: - zilog_error("%s: probing IR %s on %s (i2c-%d) failed with %d\n", - __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, -@@ -1438,7 +1637,6 @@ static int __init zilog_init(void) - zilog_notify("Zilog/Hauppauge IR driver initializing\n"); - - mutex_init(&tx_data_lock); -- mutex_init(&ir_devices_lock); - - request_module("firmware_class"); - -diff --git a/include/media/rc-map.h b/include/media/rc-map.h -index d843afc..9184751 100644 ---- a/include/media/rc-map.h -+++ b/include/media/rc-map.h -@@ -94,7 +94,7 @@ void rc_map_init(void); - #define RC_MAP_GADMEI_RM008Z "rc-gadmei-rm008z" - #define RC_MAP_GENIUS_TVGO_A11MCE "rc-genius-tvgo-a11mce" - #define RC_MAP_GOTVIEW7135 "rc-gotview7135" --#define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge-new" -+#define RC_MAP_HAUPPAUGE_NEW "rc-hauppauge" - #define RC_MAP_IMON_MCE "rc-imon-mce" - #define RC_MAP_IMON_PAD "rc-imon-pad" - #define RC_MAP_IODATA_BCTV7E "rc-iodata-bctv7e" -@@ -125,7 +125,7 @@ void rc_map_init(void); - #define RC_MAP_PROTEUS_2309 "rc-proteus-2309" - #define RC_MAP_PURPLETV "rc-purpletv" - #define RC_MAP_PV951 "rc-pv951" --#define RC_MAP_RC5_HAUPPAUGE_NEW "rc-rc5-hauppauge-new" -+#define RC_MAP_HAUPPAUGE "rc-hauppauge" - #define RC_MAP_RC5_TV "rc-rc5-tv" - #define RC_MAP_RC6_MCE "rc-rc6-mce" - #define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys" -diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h -index 6e96b26..f80b537 100644 ---- a/include/media/soc_camera.h -+++ b/include/media/soc_camera.h -@@ -30,6 +30,8 @@ struct soc_camera_device { - struct device *pdev; /* Platform device */ - s32 user_width; - s32 user_height; -+ u32 bytesperline; /* for padding, zero if unused */ -+ u32 sizeimage; - enum v4l2_colorspace colorspace; - unsigned char iface; /* Host number */ - unsigned char devnum; /* Device number per host */ diff --git a/pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch b/pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch deleted file mode 100644 index 0c7f592ac..000000000 --- a/pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.patch +++ /dev/null @@ -1,112 +0,0 @@ -From: Naga Chumbalkar -Date: Mon, 21 Mar 2011 03:29:08 +0000 (+0000) -Subject: PCI: PCIe links may not get configured for ASPM under POWERSAVE mode -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=1a680b7c325882188865f05b9a88d32f75f26495 - -PCI: PCIe links may not get configured for ASPM under POWERSAVE mode - -v3 -> v2: Moved ASPM enabling logic to pci_set_power_state() -v2 -> v1: Preserved the logic in pci_raw_set_power_state() - : Added ASPM enabling logic after scanning Root Bridge - : http://marc.info/?l=linux-pci&m=130046996216391&w=2 -v1 : http://marc.info/?l=linux-pci&m=130013164703283&w=2 - -The assumption made in commit 41cd766b065970ff6f6c89dd1cf55fa706c84a3d -(PCI: Don't enable aspm before drivers have had a chance to veto it) that -pci_enable_device() will result in re-configuring ASPM when aspm_policy is -POWERSAVE is no longer valid. This is due to commit -97c145f7c87453cec90e91238fba5fe2c1561b32 (PCI: read current power state -at enable time) which resets dev->current_state to D0. Due to this the -call to pcie_aspm_pm_state_change() is never made. Note the equality check -(below) that returns early: -./drivers/pci/pci.c: pci_raw_set_pci_power_state() -546 /* Check if we're already there */ -547 if (dev->current_state == state) -548 return 0; - -Therefore OSPM never configures the PCIe links for ASPM to turn them "on". - -Fix it by configuring ASPM from the pci_enable_device() code path. This -also allows a driver such as the e1000e networking driver a chance to -disable ASPM (L0s, L1), if need be, prior to enabling the device. A -driver may perform this action if the device is known to mis-behave -wrt ASPM. - -Signed-off-by: Naga Chumbalkar -Acked-by: Rafael J. Wysocki -Cc: Matthew Garrett -Signed-off-by: Jesse Barnes ---- - -diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c -index b714d78..2472e71 100644 ---- a/drivers/pci/pci.c -+++ b/drivers/pci/pci.c -@@ -740,6 +740,12 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) - - if (!__pci_complete_power_transition(dev, state)) - error = 0; -+ /* -+ * When aspm_policy is "powersave" this call ensures -+ * that ASPM is configured. -+ */ -+ if (!error && dev->bus->self) -+ pcie_aspm_powersave_config_link(dev->bus->self); - - return error; - } -diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c -index bbdb4fd..e61b82e 100644 ---- a/drivers/pci/pcie/aspm.c -+++ b/drivers/pci/pcie/aspm.c -@@ -708,6 +708,28 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) - up_read(&pci_bus_sem); - } - -+void pcie_aspm_powersave_config_link(struct pci_dev *pdev) -+{ -+ struct pcie_link_state *link = pdev->link_state; -+ -+ if (aspm_disabled || !pci_is_pcie(pdev) || !link) -+ return; -+ -+ if (aspm_policy != POLICY_POWERSAVE) -+ return; -+ -+ if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && -+ (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) -+ return; -+ -+ down_read(&pci_bus_sem); -+ mutex_lock(&aspm_lock); -+ pcie_config_aspm_path(link); -+ pcie_set_clkpm(link, policy_to_clkpm_state(link)); -+ mutex_unlock(&aspm_lock); -+ up_read(&pci_bus_sem); -+} -+ - /* - * pci_disable_link_state - disable pci device's link state, so the link will - * never enter specific states -diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h -index ce68105..67cb3ae 100644 ---- a/include/linux/pci-aspm.h -+++ b/include/linux/pci-aspm.h -@@ -26,6 +26,7 @@ - extern void pcie_aspm_init_link_state(struct pci_dev *pdev); - extern void pcie_aspm_exit_link_state(struct pci_dev *pdev); - extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); -+extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev); - extern void pci_disable_link_state(struct pci_dev *pdev, int state); - extern void pcie_clear_aspm(void); - extern void pcie_no_aspm(void); -@@ -39,6 +40,9 @@ static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) - static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) - { - } -+static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) -+{ -+} - static inline void pci_disable_link_state(struct pci_dev *pdev, int state) - { - } diff --git a/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch b/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch deleted file mode 100644 index 73885ae57..000000000 --- a/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch +++ /dev/null @@ -1,214 +0,0 @@ -From: Kay Sievers -Date: Sun, 13 Mar 2011 02:19:51 +0000 (+0100) -Subject: printk: do not mangle valid userspace syslog prefixes -X-Git-Tag: v2.6.39-rc1~471^2 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9d90c8d9cde929cbc575098e825d7c29d9f45054 - -printk: do not mangle valid userspace syslog prefixes - -printk: do not mangle valid userspace syslog prefixes with /dev/kmsg - -Log messages passed to the kernel log by using /dev/kmsg or /dev/ttyprintk -might contain a syslog prefix including the syslog facility value. - -This makes printk to recognize these headers properly, extract the real log -level from it to use, and add the prefix as a proper prefix to the -log buffer, instead of wrongly printing it as the log message text. - -Before: - $ echo '<14>text' > /dev/kmsg - $ dmesg -r - <4>[135159.594810] <14>text - -After: - $ echo '<14>text' > /dev/kmsg - $ dmesg -r - <14>[ 50.750654] text - -Cc: Lennart Poettering -Signed-off-by: Kay Sievers -Signed-off-by: Greg Kroah-Hartman ---- - -diff --git a/kernel/printk.c b/kernel/printk.c -index 2ddbdc7..5e3d042 100644 ---- a/kernel/printk.c -+++ b/kernel/printk.c -@@ -499,6 +499,71 @@ static void _call_console_drivers(unsigned start, - } - - /* -+ * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the -+ * lower 3 bit are the log level, the rest are the log facility. In case -+ * userspace passes usual userspace syslog messages to /dev/kmsg or -+ * /dev/ttyprintk, the log prefix might contain the facility. Printk needs -+ * to extract the correct log level for in-kernel processing, and not mangle -+ * the original value. -+ * -+ * If a prefix is found, the length of the prefix is returned. If 'level' is -+ * passed, it will be filled in with the log level without a possible facility -+ * value. If 'special' is passed, the special printk prefix chars are accepted -+ * and returned. If no valid header is found, 0 is returned and the passed -+ * variables are not touched. -+ */ -+static size_t log_prefix(const char *p, unsigned int *level, char *special) -+{ -+ unsigned int lev = 0; -+ char sp = '\0'; -+ size_t len; -+ -+ if (p[0] != '<' || !p[1]) -+ return 0; -+ if (p[2] == '>') { -+ /* usual single digit level number or special char */ -+ switch (p[1]) { -+ case '0' ... '7': -+ lev = p[1] - '0'; -+ break; -+ case 'c': /* KERN_CONT */ -+ case 'd': /* KERN_DEFAULT */ -+ sp = p[1]; -+ break; -+ default: -+ return 0; -+ } -+ len = 3; -+ } else { -+ /* multi digit including the level and facility number */ -+ char *endp = NULL; -+ -+ if (p[1] < '0' && p[1] > '9') -+ return 0; -+ -+ lev = (simple_strtoul(&p[1], &endp, 10) & 7); -+ if (endp == NULL || endp[0] != '>') -+ return 0; -+ len = (endp + 1) - p; -+ } -+ -+ /* do not accept special char if not asked for */ -+ if (sp && !special) -+ return 0; -+ -+ if (special) { -+ *special = sp; -+ /* return special char, do not touch level */ -+ if (sp) -+ return len; -+ } -+ -+ if (level) -+ *level = lev; -+ return len; -+} -+ -+/* - * Call the console drivers, asking them to write out - * log_buf[start] to log_buf[end - 1]. - * The console_lock must be held. -@@ -513,13 +578,9 @@ static void call_console_drivers(unsigned start, unsigned end) - cur_index = start; - start_print = start; - while (cur_index != end) { -- if (msg_level < 0 && ((end - cur_index) > 2) && -- LOG_BUF(cur_index + 0) == '<' && -- LOG_BUF(cur_index + 1) >= '0' && -- LOG_BUF(cur_index + 1) <= '7' && -- LOG_BUF(cur_index + 2) == '>') { -- msg_level = LOG_BUF(cur_index + 1) - '0'; -- cur_index += 3; -+ if (msg_level < 0 && ((end - cur_index) > 2)) { -+ /* strip log prefix */ -+ cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL); - start_print = cur_index; - } - while (cur_index != end) { -@@ -717,6 +778,8 @@ asmlinkage int vprintk(const char *fmt, va_list args) - unsigned long flags; - int this_cpu; - char *p; -+ size_t plen; -+ char special; - - boot_delay_msec(); - printk_delay(); -@@ -757,45 +820,52 @@ asmlinkage int vprintk(const char *fmt, va_list args) - printed_len += vscnprintf(printk_buf + printed_len, - sizeof(printk_buf) - printed_len, fmt, args); - -- - p = printk_buf; - -- /* Do we have a loglevel in the string? */ -- if (p[0] == '<') { -- unsigned char c = p[1]; -- if (c && p[2] == '>') { -- switch (c) { -- case '0' ... '7': /* loglevel */ -- current_log_level = c - '0'; -- /* Fallthrough - make sure we're on a new line */ -- case 'd': /* KERN_DEFAULT */ -- if (!new_text_line) { -- emit_log_char('\n'); -- new_text_line = 1; -- } -- /* Fallthrough - skip the loglevel */ -- case 'c': /* KERN_CONT */ -- p += 3; -- break; -+ /* Read log level and handle special printk prefix */ -+ plen = log_prefix(p, ¤t_log_level, &special); -+ if (plen) { -+ p += plen; -+ -+ switch (special) { -+ case 'c': /* Strip KERN_CONT, continue line */ -+ plen = 0; -+ break; -+ case 'd': /* Strip KERN_DEFAULT, start new line */ -+ plen = 0; -+ default: -+ if (!new_text_line) { -+ emit_log_char('\n'); -+ new_text_line = 1; - } - } - } - - /* -- * Copy the output into log_buf. If the caller didn't provide -- * appropriate log level tags, we insert them here -+ * Copy the output into log_buf. If the caller didn't provide -+ * the appropriate log prefix, we insert them here - */ -- for ( ; *p; p++) { -+ for (; *p; p++) { - if (new_text_line) { -- /* Always output the token */ -- emit_log_char('<'); -- emit_log_char(current_log_level + '0'); -- emit_log_char('>'); -- printed_len += 3; - new_text_line = 0; - -+ if (plen) { -+ /* Copy original log prefix */ -+ int i; -+ -+ for (i = 0; i < plen; i++) -+ emit_log_char(printk_buf[i]); -+ printed_len += plen; -+ } else { -+ /* Add log prefix */ -+ emit_log_char('<'); -+ emit_log_char(current_log_level + '0'); -+ emit_log_char('>'); -+ printed_len += 3; -+ } -+ - if (printk_time) { -- /* Follow the token with the time */ -+ /* Add the current time stamp */ - char tbuf[50], *tp; - unsigned tlen; - unsigned long long t; diff --git a/scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch b/scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch deleted file mode 100644 index faded334b..000000000 --- a/scsi_dh_hp_sw-fix-deadlock-in-start_stop_endio.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 7a1e9d829f8bd821466c5ea834ad6f378740d2be Mon Sep 17 00:00:00 2001 -From: Mike Snitzer -Date: Tue, 25 Jan 2011 11:52:17 -0500 -Subject: [SCSI] scsi_dh_hp_sw: fix deadlock in start_stop_endio - -The use of blk_execute_rq_nowait() implies __blk_put_request() is needed -in start_stop_endio() rather than blk_put_request() -- -blk_finish_request() is called with queue lock already held. - -Signed-off-by: Mike Snitzer -Signed-off-by: James Bottomley ---- - drivers/scsi/device_handler/scsi_dh_hp_sw.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c -index e391664..d0363c8 100644 ---- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c -+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c -@@ -225,7 +225,8 @@ static void start_stop_endio(struct request *req, int error) - } - } - done: -- blk_put_request(req); -+ req->end_io_data = NULL; -+ __blk_put_request(req->q, req); - if (h->callback_fn) { - h->callback_fn(h->callback_data, err); - h->callback_fn = h->callback_data = NULL; --- -1.7.5.1 - diff --git a/sources b/sources index b519133bb..c8ff5a031 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -7d471477bfa67546f902da62227fa976 linux-2.6.38.tar.bz2 -c0f416f6a2e916633f697287cc7cb914 patch-2.6.38.8.bz2 +1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 diff --git a/x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch b/x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch deleted file mode 100644 index 36eae4b97..000000000 --- a/x86-dumpstack-correct-stack-dump-info-when-frame-pointer-is-available.patch +++ /dev/null @@ -1,352 +0,0 @@ -From: Namhyung Kim -Date: Fri, 18 Mar 2011 02:40:06 +0000 (+0900) -Subject: x86, dumpstack: Correct stack dump info when frame pointer is available -X-Git-Tag: v2.6.39-rc1~64^2~7 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=e8e999cf3cc733482e390b02ff25a64cecdc0b64 - -x86, dumpstack: Correct stack dump info when frame pointer is available - -Current stack dump code scans entire stack and check each entry -contains a pointer to kernel code. If CONFIG_FRAME_POINTER=y it -could mark whether the pointer is valid or not based on value of -the frame pointer. Invalid entries could be preceded by '?' sign. - -However this was not going to happen because scan start point -was always higher than the frame pointer so that they could not -meet. - -Commit 9c0729dc8062 ("x86: Eliminate bp argument from the stack -tracing routines") delayed bp acquisition point, so the bp was -read in lower frame, thus all of the entries were marked -invalid. - -This patch fixes this by reverting above commit while retaining -stack_frame() helper as suggested by Frederic Weisbecker. - -End result looks like below: - -before: - - [ 3.508329] Call Trace: - [ 3.508551] [] ? panic+0x91/0x199 - [ 3.508662] [] ? printk+0x68/0x6a - [ 3.508770] [] ? mount_block_root+0x257/0x26e - [ 3.508876] [] ? mount_root+0x56/0x5a - [ 3.508975] [] ? prepare_namespace+0x170/0x1a9 - [ 3.509216] [] ? kernel_init+0x1d2/0x1e2 - [ 3.509335] [] ? kernel_thread_helper+0x4/0x10 - [ 3.509442] [] ? restore_args+0x0/0x30 - [ 3.509542] [] ? kernel_init+0x0/0x1e2 - [ 3.509641] [] ? kernel_thread_helper+0x0/0x10 - -after: - - [ 3.522991] Call Trace: - [ 3.523351] [] panic+0x91/0x199 - [ 3.523468] [] ? printk+0x68/0x6a - [ 3.523576] [] mount_block_root+0x257/0x26e - [ 3.523681] [] mount_root+0x56/0x5a - [ 3.523780] [] prepare_namespace+0x170/0x1a9 - [ 3.523885] [] kernel_init+0x1d2/0x1e2 - [ 3.523987] [] kernel_thread_helper+0x4/0x10 - [ 3.524228] [] ? restore_args+0x0/0x30 - [ 3.524345] [] ? kernel_init+0x0/0x1e2 - [ 3.524445] [] ? kernel_thread_helper+0x0/0x10 - - -v5: - * fix build breakage with oprofile - - -v4: - * use 0 instead of regs->bp - * separate out printk changes - - -v3: - * apply comment from Frederic - * add a couple of printk fixes - -Signed-off-by: Namhyung Kim -Acked-by: Peter Zijlstra -Acked-by: Frederic Weisbecker -Cc: Soren Sandmann -Cc: Paul Mackerras -Cc: Arnaldo Carvalho de Melo -Cc: Robert Richter -LKML-Reference: <1300416006-3163-1-git-send-email-namhyung@gmail.com> -Signed-off-by: Ingo Molnar ---- - -diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h -index 518bbbb..fe2cc6e 100644 ---- a/arch/x86/include/asm/kdebug.h -+++ b/arch/x86/include/asm/kdebug.h -@@ -26,7 +26,7 @@ extern void die(const char *, struct pt_regs *,long); - extern int __must_check __die(const char *, struct pt_regs *, long); - extern void show_registers(struct pt_regs *regs); - extern void show_trace(struct task_struct *t, struct pt_regs *regs, -- unsigned long *sp); -+ unsigned long *sp, unsigned long bp); - extern void __show_regs(struct pt_regs *regs, int all); - extern void show_regs(struct pt_regs *regs); - extern unsigned long oops_begin(void); -diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h -index 52b5c7e..d7e89c8 100644 ---- a/arch/x86/include/asm/stacktrace.h -+++ b/arch/x86/include/asm/stacktrace.h -@@ -47,7 +47,7 @@ struct stacktrace_ops { - }; - - void dump_trace(struct task_struct *tsk, struct pt_regs *regs, -- unsigned long *stack, -+ unsigned long *stack, unsigned long bp, - const struct stacktrace_ops *ops, void *data); - - #ifdef CONFIG_X86_32 -@@ -86,11 +86,11 @@ stack_frame(struct task_struct *task, struct pt_regs *regs) - - extern void - show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, -- unsigned long *stack, char *log_lvl); -+ unsigned long *stack, unsigned long bp, char *log_lvl); - - extern void - show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, -- unsigned long *sp, char *log_lvl); -+ unsigned long *sp, unsigned long bp, char *log_lvl); - - extern unsigned int code_bytes; - -diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c -index 279bc9d..3061276 100644 ---- a/arch/x86/kernel/cpu/perf_event.c -+++ b/arch/x86/kernel/cpu/perf_event.c -@@ -1792,7 +1792,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) - - perf_callchain_store(entry, regs->ip); - -- dump_trace(NULL, regs, NULL, &backtrace_ops, entry); -+ dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); - } - - #ifdef CONFIG_COMPAT -diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c -index 220a1c1..999e279 100644 ---- a/arch/x86/kernel/dumpstack.c -+++ b/arch/x86/kernel/dumpstack.c -@@ -175,21 +175,21 @@ static const struct stacktrace_ops print_trace_ops = { - - void - show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, -- unsigned long *stack, char *log_lvl) -+ unsigned long *stack, unsigned long bp, char *log_lvl) - { - printk("%sCall Trace:\n", log_lvl); -- dump_trace(task, regs, stack, &print_trace_ops, log_lvl); -+ dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); - } - - void show_trace(struct task_struct *task, struct pt_regs *regs, -- unsigned long *stack) -+ unsigned long *stack, unsigned long bp) - { -- show_trace_log_lvl(task, regs, stack, ""); -+ show_trace_log_lvl(task, regs, stack, bp, ""); - } - - void show_stack(struct task_struct *task, unsigned long *sp) - { -- show_stack_log_lvl(task, NULL, sp, ""); -+ show_stack_log_lvl(task, NULL, sp, 0, ""); - } - - /* -@@ -197,14 +197,16 @@ void show_stack(struct task_struct *task, unsigned long *sp) - */ - void dump_stack(void) - { -+ unsigned long bp; - unsigned long stack; - -+ bp = stack_frame(current, NULL); - printk("Pid: %d, comm: %.20s %s %s %.*s\n", - current->pid, current->comm, print_tainted(), - init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); -- show_trace(NULL, NULL, &stack); -+ show_trace(NULL, NULL, &stack, bp); - } - EXPORT_SYMBOL(dump_stack); - -diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c -index 74cc1ed..3b97a80 100644 ---- a/arch/x86/kernel/dumpstack_32.c -+++ b/arch/x86/kernel/dumpstack_32.c -@@ -17,12 +17,11 @@ - #include - - --void dump_trace(struct task_struct *task, -- struct pt_regs *regs, unsigned long *stack, -+void dump_trace(struct task_struct *task, struct pt_regs *regs, -+ unsigned long *stack, unsigned long bp, - const struct stacktrace_ops *ops, void *data) - { - int graph = 0; -- unsigned long bp; - - if (!task) - task = current; -@@ -35,7 +34,9 @@ void dump_trace(struct task_struct *task, - stack = (unsigned long *)task->thread.sp; - } - -- bp = stack_frame(task, regs); -+ if (!bp) -+ bp = stack_frame(task, regs); -+ - for (;;) { - struct thread_info *context; - -@@ -55,7 +56,7 @@ EXPORT_SYMBOL(dump_trace); - - void - show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, -- unsigned long *sp, char *log_lvl) -+ unsigned long *sp, unsigned long bp, char *log_lvl) - { - unsigned long *stack; - int i; -@@ -77,7 +78,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, - touch_nmi_watchdog(); - } - printk(KERN_CONT "\n"); -- show_trace_log_lvl(task, regs, sp, log_lvl); -+ show_trace_log_lvl(task, regs, sp, bp, log_lvl); - } - - -@@ -102,7 +103,7 @@ void show_registers(struct pt_regs *regs) - u8 *ip; - - printk(KERN_EMERG "Stack:\n"); -- show_stack_log_lvl(NULL, regs, ®s->sp, KERN_EMERG); -+ show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG); - - printk(KERN_EMERG "Code: "); - -diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c -index a6b6fcf..e71c98d 100644 ---- a/arch/x86/kernel/dumpstack_64.c -+++ b/arch/x86/kernel/dumpstack_64.c -@@ -139,8 +139,8 @@ fixup_bp_irq_link(unsigned long bp, unsigned long *stack, - * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack - */ - --void dump_trace(struct task_struct *task, -- struct pt_regs *regs, unsigned long *stack, -+void dump_trace(struct task_struct *task, struct pt_regs *regs, -+ unsigned long *stack, unsigned long bp, - const struct stacktrace_ops *ops, void *data) - { - const unsigned cpu = get_cpu(); -@@ -150,7 +150,6 @@ void dump_trace(struct task_struct *task, - struct thread_info *tinfo; - int graph = 0; - unsigned long dummy; -- unsigned long bp; - - if (!task) - task = current; -@@ -161,7 +160,8 @@ void dump_trace(struct task_struct *task, - stack = (unsigned long *)task->thread.sp; - } - -- bp = stack_frame(task, regs); -+ if (!bp) -+ bp = stack_frame(task, regs); - /* - * Print function call entries in all stacks, starting at the - * current stack address. If the stacks consist of nested -@@ -225,7 +225,7 @@ EXPORT_SYMBOL(dump_trace); - - void - show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, -- unsigned long *sp, char *log_lvl) -+ unsigned long *sp, unsigned long bp, char *log_lvl) - { - unsigned long *irq_stack_end; - unsigned long *irq_stack; -@@ -269,7 +269,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, - preempt_enable(); - - printk(KERN_CONT "\n"); -- show_trace_log_lvl(task, regs, sp, log_lvl); -+ show_trace_log_lvl(task, regs, sp, bp, log_lvl); - } - - void show_registers(struct pt_regs *regs) -@@ -298,7 +298,7 @@ void show_registers(struct pt_regs *regs) - - printk(KERN_EMERG "Stack:\n"); - show_stack_log_lvl(NULL, regs, (unsigned long *)sp, -- KERN_EMERG); -+ 0, KERN_EMERG); - - printk(KERN_EMERG "Code: "); - -diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c -index 99fa3ad..d46cbe4 100644 ---- a/arch/x86/kernel/process.c -+++ b/arch/x86/kernel/process.c -@@ -87,7 +87,7 @@ void exit_thread(void) - void show_regs(struct pt_regs *regs) - { - show_registers(regs); -- show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs)); -+ show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs), 0); - } - - void show_regs_common(void) -diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c -index 938c8e1..6515733 100644 ---- a/arch/x86/kernel/stacktrace.c -+++ b/arch/x86/kernel/stacktrace.c -@@ -73,7 +73,7 @@ static const struct stacktrace_ops save_stack_ops_nosched = { - */ - void save_stack_trace(struct stack_trace *trace) - { -- dump_trace(current, NULL, NULL, &save_stack_ops, trace); -+ dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace); - if (trace->nr_entries < trace->max_entries) - trace->entries[trace->nr_entries++] = ULONG_MAX; - } -@@ -81,14 +81,14 @@ EXPORT_SYMBOL_GPL(save_stack_trace); - - void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs) - { -- dump_trace(current, regs, NULL, &save_stack_ops, trace); -+ dump_trace(current, regs, NULL, 0, &save_stack_ops, trace); - if (trace->nr_entries < trace->max_entries) - trace->entries[trace->nr_entries++] = ULONG_MAX; - } - - void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) - { -- dump_trace(tsk, NULL, NULL, &save_stack_ops_nosched, trace); -+ dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace); - if (trace->nr_entries < trace->max_entries) - trace->entries[trace->nr_entries++] = ULONG_MAX; - } -diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c -index 72cbec1..2d49d4e 100644 ---- a/arch/x86/oprofile/backtrace.c -+++ b/arch/x86/oprofile/backtrace.c -@@ -126,7 +126,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) - if (!user_mode_vm(regs)) { - unsigned long stack = kernel_stack_pointer(regs); - if (depth) -- dump_trace(NULL, regs, (unsigned long *)stack, -+ dump_trace(NULL, regs, (unsigned long *)stack, 0, - &backtrace_ops, &depth); - return; - } From 24958d9bb67862c58e5a7c41d890ede10ef9eca9 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert Date: Fri, 1 Jul 2011 03:30:17 -0400 Subject: [PATCH 97/99] Upload patch-2.6.39.2.bz2 --- sources | 1 + 1 file changed, 1 insertion(+) diff --git a/sources b/sources index c8ff5a031..e7c84836a 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 +6f81e64e790eb7847773eec4f7cbf207 patch-2.6.39.2.bz2 From e99605611a38001bc5458a0b2c15e92b8e3178a8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 12 Jul 2011 20:17:56 -0400 Subject: [PATCH 98/99] 2.6.39.2 --- ...le-fast-channel-switching-by-default.patch | 72 ---------------- ...cking-around-ioc-ioc-data-assignment.patch | 44 ---------- ...rkaround-for-bsd-ring-on-sandybridge.patch | 43 ---------- drm-i915-snb-irq-stalls-fix.patch | 53 ------------ kernel.spec | 30 +++---- ...reference-in-scan-get-next-rmap-item.patch | 82 ------------------- linux-2.6-silence-noise.patch | 10 +-- sources | 1 + 8 files changed, 16 insertions(+), 319 deletions(-) delete mode 100644 ath5k-disable-fast-channel-switching-by-default.patch delete mode 100644 cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch delete mode 100644 drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch delete mode 100644 drm-i915-snb-irq-stalls-fix.patch delete mode 100644 ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch diff --git a/ath5k-disable-fast-channel-switching-by-default.patch b/ath5k-disable-fast-channel-switching-by-default.patch deleted file mode 100644 index a26eb51d9..000000000 --- a/ath5k-disable-fast-channel-switching-by-default.patch +++ /dev/null @@ -1,72 +0,0 @@ -From c564db51fe187362c4da0a9de2905c020e981c75 Mon Sep 17 00:00:00 2001 -From: Nick Kossifidis -Date: Thu, 2 Jun 2011 03:09:48 +0300 -Subject: ath5k: Disable fast channel switching by default - -Disable fast channel change by default on AR2413/AR5413 due to -some bug reports (it still works for me but it's better to be safe). -Add a module parameter "fastchanswitch" in case anyone wants to enable -it and play with it. - -Signed-off-by: Nick Kossifidis -Tested-by: Sedat Dilek -Signed-off-by: John W. Linville ---- - drivers/net/wireless/ath/ath5k/base.c | 9 ++++++++- - drivers/net/wireless/ath/ath5k/reset.c | 5 ++++- - 2 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c -index 09ae4ef..0fb6333 100644 ---- a/drivers/net/wireless/ath/ath5k/base.c -+++ b/drivers/net/wireless/ath/ath5k/base.c -@@ -69,6 +69,11 @@ static int modparam_all_channels; - module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); - MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); - -+static int modparam_fastchanswitch; -+module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); -+MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); -+ -+ - /* Module info */ - MODULE_AUTHOR("Jiri Slaby"); - MODULE_AUTHOR("Nick Kossifidis"); -@@ -2664,6 +2669,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, - struct ath5k_hw *ah = sc->ah; - struct ath_common *common = ath5k_hw_common(ah); - int ret, ani_mode; -+ bool fast; - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); - -@@ -2669,7 +2669,8 @@ ath5k_reset(struct ath5k_softc *sc, stru - ath5k_drain_tx_buffs(sc); - if (chan) - sc->curchan = chan; -- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, -+ fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; -+ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, - skip_pcu); - if (ret) { - ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); -diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c -index 8420689..6f53d2b 100644 ---- a/drivers/net/wireless/ath/ath5k/reset.c -+++ b/drivers/net/wireless/ath/ath5k/reset.c -@@ -1119,8 +1119,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - /* Non fatal, can happen eg. - * on mode change */ - ret = 0; -- } else -+ } else { -+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, -+ "fast chan change successful\n"); - return 0; -+ } - } - - /* --- -1.7.5.2 - diff --git a/cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch b/cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch deleted file mode 100644 index bb04d63df..000000000 --- a/cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Jens Axboe -Date: Sun, 5 Jun 2011 04:01:13 +0000 (+0200) -Subject: cfq-iosched: fix locking around ioc->ioc_data assignment -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ab4bd22d3cce6977dc039664cc2d052e3147d662 - -cfq-iosched: fix locking around ioc->ioc_data assignment - -Since we are modifying this RCU pointer, we need to hold -the lock protecting it around it. - -This fixes a potential reuse and double free of a cfq -io_context structure. The bug has been in CFQ for a long -time, it hit very few people but those it did hit seemed -to see it a lot. - -Tracked in RH bugzilla here: - -https://bugzilla.redhat.com/show_bug.cgi?id=577968 - -Credit goes to Paul Bolle for figuring out that the issue -was around the one-hit ioc->ioc_data cache. Thanks to his -hard work the issue is now fixed. - -Cc: stable@kernel.org -Signed-off-by: Jens Axboe ---- - -diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c -index 3c7b537..545b8d4 100644 ---- a/block/cfq-iosched.c -+++ b/block/cfq-iosched.c -@@ -2772,8 +2772,11 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, - smp_wmb(); - cic->key = cfqd_dead_key(cfqd); - -- if (ioc->ioc_data == cic) -+ if (rcu_dereference(ioc->ioc_data) == cic) { -+ spin_lock(&ioc->lock); - rcu_assign_pointer(ioc->ioc_data, NULL); -+ spin_unlock(&ioc->lock); -+ } - - if (cic->cfqq[BLK_RW_ASYNC]) { - cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); diff --git a/drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch b/drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch deleted file mode 100644 index 06a8650b1..000000000 --- a/drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch +++ /dev/null @@ -1,43 +0,0 @@ -From: Chris Wilson -Date: Tue, 21 Jun 2011 17:37:59 +0000 (+0100) -Subject: drm/i915: Apply HWSTAM workaround for BSD ring on SandyBridge -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=ec6a890dfed7dd245beba5e5bcdfcffbd934c284 - -drm/i915: Apply HWSTAM workaround for BSD ring on SandyBridge - -...we need to apply exactly the same workaround for missing interrupts -from BSD as for the BLT ring, apparently. - -See also commit 498e720b96379d8ee9c294950a01534a73defcf3 -(drm/i915: Fix gen6 (SNB) missed BLT ring interrupts). - -Reported-and-tested-by: nkalkhof@web.de -Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38529 -Signed-off-by: Chris Wilson -Signed-off-by: Keith Packard ---- - -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index 9e34a1a..ae2b499 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -1749,6 +1749,7 @@ void ironlake_irq_preinstall(struct drm_device *dev) - * happens. - */ - I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); -+ I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT); - } - - /* XXX hotplug from PCH */ -diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h -index 2f967af..5d5def7 100644 ---- a/drivers/gpu/drm/i915/i915_reg.h -+++ b/drivers/gpu/drm/i915/i915_reg.h -@@ -531,6 +531,7 @@ - #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 - #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) - -+#define GEN6_BSD_HWSTAM 0x12098 - #define GEN6_BSD_IMR 0x120a8 - #define GEN6_BSD_USER_INTERRUPT (1 << 12) - diff --git a/drm-i915-snb-irq-stalls-fix.patch b/drm-i915-snb-irq-stalls-fix.patch deleted file mode 100644 index acf64da47..000000000 --- a/drm-i915-snb-irq-stalls-fix.patch +++ /dev/null @@ -1,53 +0,0 @@ -commit 498e720b96379d8ee9c294950a01534a73defcf3 -Author: Daniel J Blueman -Date: Fri Jun 17 11:32:19 2011 -0700 - - drm/i915: Fix gen6 (SNB) missed BLT ring interrupts. - - The failure appeared in dmesg as: - - [drm:i915_hangcheck_ring_idle] *ERROR* Hangcheck timer elapsed... blt - ring idle [waiting on 35064155, at 35064155], missed IRQ? - - This works around that problem on by making the blitter command - streamer write interrupt state to the Hardware Status Page when a - MI_USER_INTERRUPT command is decoded, which appears to force the seqno - out to memory before the interrupt happens. - - v1->v2: Moved to prior interrupt handler installation and RMW flags as - per feedback. - v2->v3: Removed RMW of flags (by anholt) - - Cc: stable@kernel.org - Signed-off-by: Daniel J Blueman - Signed-off-by: Eric Anholt - Tested-by: Chris Wilson [v1] - Tested-by: Eric Anholt [v1,v3] - (incidence of the bug with a testcase went from avg 2/1000 to - 0/12651 in the latest test run (plus more for v1)) - Tested-by: Kenneth Graunke [v1] - Tested-by: Robert Hooker [v1] - Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=33394 - Signed-off-by: Dave Airlie - -diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c -index b9fafe3..9e34a1a 100644 ---- a/drivers/gpu/drm/i915/i915_irq.c -+++ b/drivers/gpu/drm/i915/i915_irq.c -@@ -1740,6 +1740,16 @@ void ironlake_irq_preinstall(struct drm_device *dev) - INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work); - - I915_WRITE(HWSTAM, 0xeffe); -+ if (IS_GEN6(dev)) { -+ /* Workaround stalls observed on Sandy Bridge GPUs by -+ * making the blitter command streamer generate a -+ * write to the Hardware Status Page for -+ * MI_USER_INTERRUPT. This appears to serialize the -+ * previous seqno write out before the interrupt -+ * happens. -+ */ -+ I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); -+ } - - /* XXX hotplug from PCH */ - diff --git a/kernel.spec b/kernel.spec index 397f648c1..b75966edb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -63,7 +63,7 @@ Summary: The Linux kernel %if 0%{?released_kernel} # Do we have a -stable update to apply? -%define stable_update 2 +%define stable_update 3 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -614,9 +614,6 @@ Patch30: linux-2.6-tracehook.patch Patch31: linux-2.6-utrace.patch Patch32: linux-2.6-utrace-ptrace.patch -# CVE-2011-2183 -Patch80: ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch - Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch Patch160: linux-2.6-32bit-mmap-exec-randomization.patch @@ -654,7 +651,6 @@ Patch570: linux-2.6-selinux-mprotect-checks.patch Patch580: linux-2.6-sparc-selinux-mprotect-checks.patch # scsi / block -Patch603: cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch # libata Patch621: libata-sas-only-set-frozen-flag-if-new-eh-is-supported.patch @@ -681,8 +677,6 @@ Patch1824: drm-intel-next.patch # make sure the lvds comes back on lid open Patch1825: drm-intel-make-lvds-work.patch Patch1826: drm-intel-edp-fixes.patch -Patch1830: drm-i915-snb-irq-stalls-fix.patch -Patch1831: drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch # radeon - new hw + fixes for fusion and t500 regression Patch1839: drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch @@ -727,8 +721,6 @@ Patch12404: x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patc Patch12416: bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch -Patch12418: ath5k-disable-fast-channel-switching-by-default.patch - Patch12420: crypto-aesni_intel-merge-with-fpu_ko.patch %endif @@ -1173,8 +1165,6 @@ ApplyPatch linux-2.6-utrace.patch ApplyPatch linux-2.6-utrace-ptrace.patch # mm patches -# CVE-2011-2183 -ApplyPatch ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch # Architecture patches # x86(-64) @@ -1240,8 +1230,6 @@ ApplyPatch x86-pci-preserve-existing-pci-bfsort-whitelist-for-dell-systems.patch # # SCSI / block Bits. # -# rhbz#577968 -ApplyPatch cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch # libata # Fix drive detection failure on mvsas (rhbz#705019) @@ -1305,8 +1293,6 @@ ApplyPatch drm-intel-big-hammer.patch ApplyPatch drm-intel-make-lvds-work.patch ApplyPatch linux-2.6-intel-iommu-igfx.patch ApplyPatch drm-intel-edp-fixes.patch -ApplyPatch drm-i915-snb-irq-stalls-fix.patch -ApplyPatch drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch # radeon DRM (add cayman support) ApplyPatch drm-radeon-fix-regression-on-atom-cards-with-hardcoded-EDID-record.patch -R @@ -1344,9 +1330,6 @@ ApplyPatch scsi-sd-downgrade-caching-printk-from-error-to-notice.patch ApplyPatch bluetooth-device-ids-for-ath3k-on-pegatron-lucid-tablets.patch -# rhbz#709122 -ApplyPatch ath5k-disable-fast-channel-switching-by-default.patch - # rhbz#589390 ApplyPatch crypto-aesni_intel-merge-with-fpu_ko.patch @@ -1958,8 +1941,17 @@ fi # and build. %changelog +* Tue Jul 12 2011 Dave Jones +- 2.6.39.3 + dropped: (merged upstream) + ath5k-disable-fast-channel-switching-by-default.patch + cfq-iosched-fix-locking-around-ioc-ioc-data-assignment.patch + drm-i915-apply-hwstam-workaround-for-bsd-ring-on-sandybridge.patch + drm-i915-snb-irq-stalls-fix.patch + ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch + * Wed Jun 29 2011 Dave Jones -- 2.6.39 +- 2.6.39.2 * Mon Jun 27 2011 Dave Jones - Disable CONFIG_CRYPTO_MANAGER_DISABLE_TESTS, as this also disables FIPS (rhbz 716942) diff --git a/ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch b/ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch deleted file mode 100644 index d67cdc748..000000000 --- a/ksm-fix-null-pointer-dereference-in-scan-get-next-rmap-item.patch +++ /dev/null @@ -1,82 +0,0 @@ -From: Hugh Dickins -Date: Wed, 15 Jun 2011 22:08:58 +0000 (-0700) -Subject: ksm: fix NULL pointer dereference in scan_get_next_rmap_item() -X-Git-Tag: v3.0-rc4~44 -X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=2b472611a32a72f4a118c069c2d62a1a3f087afd - -ksm: fix NULL pointer dereference in scan_get_next_rmap_item() - -Andrea Righi reported a case where an exiting task can race against -ksmd::scan_get_next_rmap_item (http://lkml.org/lkml/2011/6/1/742) easily -triggering a NULL pointer dereference in ksmd. - -ksm_scan.mm_slot == &ksm_mm_head with only one registered mm - -CPU 1 (__ksm_exit) CPU 2 (scan_get_next_rmap_item) - list_empty() is false -lock slot == &ksm_mm_head -list_del(slot->mm_list) -(list now empty) -unlock - lock - slot = list_entry(slot->mm_list.next) - (list is empty, so slot is still ksm_mm_head) - unlock - slot->mm == NULL ... Oops - -Close this race by revalidating that the new slot is not simply the list -head again. - -Andrea's test case: - -#include -#include -#include -#include - -#define BUFSIZE getpagesize() - -int main(int argc, char **argv) -{ - void *ptr; - - if (posix_memalign(&ptr, getpagesize(), BUFSIZE) < 0) { - perror("posix_memalign"); - exit(1); - } - if (madvise(ptr, BUFSIZE, MADV_MERGEABLE) < 0) { - perror("madvise"); - exit(1); - } - *(char *)NULL = 0; - - return 0; -} - -Reported-by: Andrea Righi -Tested-by: Andrea Righi -Cc: Andrea Arcangeli -Signed-off-by: Hugh Dickins -Signed-off-by: Chris Wright -Cc: -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - -diff --git a/mm/ksm.c b/mm/ksm.c -index d708b3e..9a68b0c 100644 ---- a/mm/ksm.c -+++ b/mm/ksm.c -@@ -1302,6 +1302,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page) - slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list); - ksm_scan.mm_slot = slot; - spin_unlock(&ksm_mmlist_lock); -+ /* -+ * Although we tested list_empty() above, a racing __ksm_exit -+ * of the last mm on the list may have removed it since then. -+ */ -+ if (slot == &ksm_mm_head) -+ return NULL; - next_mm: - ksm_scan.address = 0; - ksm_scan.rmap_list = &slot->rmap_list; diff --git a/linux-2.6-silence-noise.patch b/linux-2.6-silence-noise.patch index 32c678b1f..11d941e46 100644 --- a/linux-2.6-silence-noise.patch +++ b/linux-2.6-silence-noise.patch @@ -57,16 +57,14 @@ in ye olde CVS tree. I have no idea why. Originally the pr_debug in device_pm_remove was nuked as well, but that seems to have gotten lost in the r1.634 of kernel.spec (2.6.26-rc2-git5.) -diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c -index 2a52270..bacbdd2 100644 ---- a/drivers/base/power/main.c -+++ b/drivers/base/power/main.c -@@ -87,8 +87,6 @@ void device_pm_unlock(void) +--- linux-2.6.39.x86_64/drivers/base/power/main.c~ 2011-07-12 19:58:19.788854464 -0400 ++++ linux-2.6.39.x86_64/drivers/base/power/main.c 2011-07-12 19:58:39.684798674 -0400 +@@ -89,8 +89,6 @@ void device_pm_unlock(void) */ void device_pm_add(struct device *dev) { - pr_debug("PM: Adding info for %s:%s\n", - dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); mutex_lock(&dpm_list_mtx); - if (dev->parent && dev->parent->power.in_suspend) + if (dev->parent && dev->parent->power.is_prepared) dev_warn(dev, "parent %s should not be sleeping\n", diff --git a/sources b/sources index e7c84836a..01f4db726 100644 --- a/sources +++ b/sources @@ -1,2 +1,3 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 +06b858e8f81600038129afe7bcd4e162 patch-2.6.39.3.bz2 6f81e64e790eb7847773eec4f7cbf207 patch-2.6.39.2.bz2 From ad87c3c819160a82532b758cead089092f178517 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 12 Jul 2011 20:19:06 -0400 Subject: [PATCH 99/99] clean up sources --- sources | 1 - 1 file changed, 1 deletion(-) diff --git a/sources b/sources index 01f4db726..a37c0a01a 100644 --- a/sources +++ b/sources @@ -1,3 +1,2 @@ 1aab7a741abe08d42e8eccf20de61e05 linux-2.6.39.tar.bz2 06b858e8f81600038129afe7bcd4e162 patch-2.6.39.3.bz2 -6f81e64e790eb7847773eec4f7cbf207 patch-2.6.39.2.bz2